我正在使用OOP PHP开发CMS。这一切都运作良好,但昨天添加新功能后,它只是崩溃。现在它在访问任何页面时检索此错误:
警告:mysqli :: mysqli():( HY000 / 1040):连接太多 第15行上的/var/www/html/Projects/CMS4/lib/DB.php连接失败: 1040连接太多致命错误:调用成员函数 在一个非对象上的render() 第33行的/var/www/html/Projects/CMS4/controllers/BaseController.php
我可以处理致命的错误。但是,关于“太多连接”错误,我理解我正在做太多调用新的mysqli(),也许我可以通过更改mysql上的max_connections来解决它,但这是否合适?或者我在代码中做错了什么我应该改进?我怎样才能减少我的联系?这是我的DB类:
db.php中
<?php
namespace Core;
if ( !class_exists( 'DB' ) ) {
class DB {
private $cxn = null;
public function __construct() {
$this->connect();
}
private function connect() {
if ( $this->cxn !== null ) {
return;
}
$this->cxn = new \mysqli( DB_HOST, DB_USER, DB_PASS, DB_NAME );
if ( $this->cxn->connect_error ) {
die( "Connection failed: " . $this->cxn->connect_errno . ' ' . $this->cxn->connect_error );
}
}
private function create_db( $name ) {
$sql = "CREATE DATABASE IF NOT EXISTS $name";
if( !$this->cxn->query( $sql ) ){
die( "Error creating database: " . $this->cxn->errno . ' ' . $this->cxn->error );
}
}
private function select_db( $name ) {
if( !$this->cxn->select_db( $name ) ){
die( "Error selecting database: " . $this->cxn->errno . ' ' . $this->cxn->error );
}
}
/**
* Create a new table in the db with the specified columns
* @param array $tables
*/
public function create_tables( $tables ) {
$sql = '';
if ( !is_array( $tables ) ) $tables = array();
foreach ( $tables as $name => $columns ) {
$sql .= "CREATE TABLE IF NOT EXISTS $name ($columns);";
}
if( !$this->cxn->multi_query( $sql ) ){
die( "Error creating table: " . $this->cxn->errno .' '. $this->cxn->error );
}
}
/**
* Insert a row in table
* @param string $table
* @param array $data
* @param array $format
* @return boolean
*/
public function insert( $table, $data, $format ) {
if ( empty($table) || empty($data) ) {
return false;
}
//cast $data and $format to array
$data = (array) $data;
$format = (array) $format;
//Build format string
$format = $this->build_format($format);
//prepare data
list($fields, $placeholders, $values) = $this->prep_query($data);
//prepend $format in to $values
array_unshift($values, $format);
//prepare statements
if ( !( $stmt = $this->cxn->prepare("INSERT INTO {$table} ({$fields}) VALUES ({$placeholders})") ) ) {
echo "Error preparating the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//Dinamically binding
if ( !call_user_func_array(array($stmt, 'bind_param'), $this->ref_values($values)) ) {
echo "Error binding parameters: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//execute the query
if (!$stmt->execute()) {
echo "Error executing the insert query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//Check for succesful insertion
if ( $stmt->affected_rows ) {
return $stmt->insert_id;
}
return false;
}
/**
* Update a row in a table
* @param string $table
* @param array $data
* @param string $format
* @param array $where
* @param string $where_format
* @return boolean
*/
public function update( $table, $data, $format, $where, $where_format ) {
if ( empty($table) || empty($data) ) {
return false;
}
//cast to array
$data = (array) $data;
$format = (array) $format;
$where_format = (array) $where_format;
//Build format string
$format = $this->build_format($format);
$where_format = $this->build_format($where_format);
$format .= $where_format;
//prepare data
list($fields, $placeholders, $values) = $this->prep_query($data, 'update');
list($where_clause, $where_values) = $this->prep_where($where);
//prepend $format onto $values
array_unshift($values, $format);
$values = array_merge($values, $where_values);
//prepare statements
if ( !( $stmt = $this->cxn->prepare("UPDATE {$table} SET {$placeholders} WHERE ({$where_clause})") ) ) {
echo "Error preparating the update query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//bind params
if ( !call_user_func_array(array($stmt, 'bind_param'), $this->ref_values($values)) ) {
echo "Error binding parameters: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//execute
if (!$stmt->execute()) {
echo "Error executing the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//Check for succesful insertion
if ( $stmt->affected_rows ) {
return true;
}
return false;
}
/**
* Delete a row from a table
* @param string $table
* @param string|array $where
* @param string|array $where_format
* @return false
*/
public function delete( $table, $where = '', $where_format = '' ) {
if ( !is_array( $where ) ) {
$where = array( 'ID' => $where );
$where_format = 'i';
}
$where_format = (array) $where_format;
$where_format = $this->build_format($where_format);
//prepare data
list($where_clause, $where_values) = $this->prep_where($where);
//prepend $format onto $values
$values = $where_values;
array_unshift($values, $where_format);
//prepare statements
if ( !( $stmt = $this->cxn->prepare("DELETE FROM {$table} WHERE {$where_clause}") ) ) {
echo "Error preparating the delete query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//bind params
if ( !call_user_func_array(array($stmt, 'bind_param'), $this->ref_values($values)) ) {
echo "Error binding parameters: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//execute
if (!$stmt->execute()) {
echo "Error executing the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//Check for succesful insertion
if ( $stmt->affected_rows ) {
return true;
}
return false;
}
/**
* Select a row from a table
* @param string $table
* @param string $where
* @param string $where_format
* @return array
*/
public function select( $table, $where = '', $where_format = '' ) {
if ( !is_array( $where ) ) {
$where = array( 'ID' => $where );
$where_format = 'i';
}
$where_format = (array) $where_format;
$where_format = $this->build_format($where_format);
//prepare data
list($where_clause, $where_values) = $this->prep_where($where);
//prepend $format onto $values
$values = $where_values;
array_unshift($values, $where_format);
//prepare statements
if ( !( $stmt = $this->cxn->prepare("SELECT * FROM {$table} WHERE {$where_clause}") ) ) {
echo "Error preparating the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//bind params
if ( !call_user_func_array(array($stmt, 'bind_param'), $this->ref_values($values)) ) {
echo "Error binding parameters: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//execute
if (!$stmt->execute()) {
echo "Error executing the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
$results = $this->get_results($stmt);
if ( $results ) {
return $results;
} else {
throw new \Exception('Invalid query, no results founds.');
}
}
/**
* Select multiple row from a table
* @param string $table
* @param string $where
* @param string $where_format
* @return array
*/
public function select_array( $table, $where = '', $where_format = '' ) {
if ( !is_array( $where ) ) {
$where = array( 'ID' => $where );
$where_format = 'i';
}
$where_format = (array) $where_format;
$where_format = $this->build_format($where_format);
//prepare data
list($where_clause, $where_values) = $this->prep_where($where);
//prepend $format onto $values
$values = $where_values;
array_unshift($values, $where_format);
//prepare statements
if ( !( $stmt = $this->cxn->prepare("SELECT * FROM {$table} WHERE {$where_clause}") ) ) {
echo "Error preparating the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//bind params
if ( !call_user_func_array(array($stmt, 'bind_param'), $this->ref_values($values)) ) {
echo "Error binding parameters: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//execute
if (!$stmt->execute()) {
echo "Error executing the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
$results = $this->get_results($stmt, 'array');
if ( $results ) {
return $results;
} else {
throw new \Exception('Invalid query, no results founds.');
}
}
/**
* Select all the rows from a table
* @param string $table
* @return array
*/
public function select_all( $table ) {
//prepare statements
if ( !( $stmt = $this->cxn->prepare("SELECT * FROM {$table}") ) ) {
echo "Error preparating the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
//execute
if (!$stmt->execute()) {
echo "Error executing the query: (" . $this->cxn->errno . ") " . $this->cxn->error;
}
$results = $this->get_results($stmt, 'array');
if ( $results ) {
return $results;
} else {
throw new \Exception('Invalid query, no results founds.');
}
}
/**
* Get results from a query
* @param object $stmt
* @param string $type
* @return array
*/
private function get_results($stmt, $type = 'string') {
$stmt->store_result();
$meta = $stmt->result_metadata();
while ( $field = $meta->fetch_field() ) {
$params[] = &$row[$field->name];
}
call_user_func_array( array( $stmt, 'bind_result' ), $params );
$results = array();
while ( $stmt->fetch() ) {
foreach( $row as $key => $val ) {
$c[$key] = $val;
}
if ($type === 'array') {
$results[] = $c;
} else {
$results = $c;
}
}
if ( !empty( $results) ) return $results;
return false;
}
/**
* Build the format string for the query values
* @param array $format
* @return string
*/
private function build_format( $format ) {
$format = implode('', $format);
$format = str_replace('%', '', $format);
return $format;
}
/**
* Prepare data for a query
* @param array $data
* @param string $type
* @return array
*/
private function prep_query($data, $type = 'insert') {
//instantiate $fields and $placeholders for looping
$fields = '';
$placeholders = '';
$values = array();
//loop through $data and build $fields, $placeholders and $values
foreach ( $data as $field => $value ) {
$fields .= "{$field},";
$values[] = $value;
if ( $type == 'update' ) {
$placeholders .= $field . '=?,';
} else {
$placeholders .= '?,';
}
}
//normalize $fields and $placeholder for inserting
$fields = substr( $fields, 0, -1 );
$placeholders = substr( $placeholders, 0, -1 );
return array( $fields, $placeholders, $values );
}
/**
* Prepare where data for a query
* @param array $where
* @return array
*/
private function prep_where($where) {
$where_clause = '';
$where_values = array();
$count = 0;
foreach ($where as $field => $value) {
if ( $count > 0 ) {
$where_clause .= ' AND ';
}
$where_clause .= $field . '=?';
$where_values[] = $value;
$count++;
}
return array($where_clause, $where_values);
}
/**
* Create references for query values
* @param array $array
* @return array
*/
private function ref_values( $array ) {
$refs = array();
foreach ( $array as $key => $value ) {
$refs[$key] = &$array[$key];
}
return $refs;
}
/**
* Hash a password
* @param string $password
* @param string $nonce
* @return string
*/
public function hash_password($password, $nonce) {
$secureHash = hash_hmac('sha512', $password . $nonce, SITE_KEY);
return $secureHash;
}
/**
* Close the connection to database
*/
private function close() {
if ( !$this->cxn->close() ) {
die('Can\'t close the connection');
}
}
}
}
?>
然后我在我的模型类中使用这些方法,就像在Page类的这个例子中一样:
模型/ page.php文件
public function insert( $data ) {
//prepare data
list($data, $cats, $tags) = $this->prep_data($data);
//insert the post
$post = $this->db->insert( $this->table, $data, 'sssss' );
//insert the post-cats relations
if ( isset( $cats ) ) {
foreach ( $cats as $cat ) {
$relation = array(
'post_id' => $post,
'term_id' => $cat,
);
$this->db->insert( 'term_relationships', $relation, 'ii' );
}
}
//insert the post-tags relations
if ( isset( $tags ) ) {
foreach ( $tags as $tag ) {
$relation = array(
'post_id' => $post,
'term_id' => $tag,
);
$this->db->insert( 'term_relationships', $relation, 'ii' );
}
}
return $post;
}
以下是整个代码:Github
答案 0 :(得分:1)
您可以将此功能用于近距离连接
function __destruct()
{
//destroy open connection
}
答案 1 :(得分:1)
看起来您正在使用常量连接到DB - 这意味着该类仅支持具有一组参数的连接。
您可以将连接设置为静态,然后无论您实例化该类多少次,每个脚本只能获得一个。 The PHP manual提供了静态使用的很好解释。
如果您需要第二次连接到不同的数据库,这将无法扩展,但到那时您将需要稍微重新考虑该类,并转移其他常量。
if ( !class_exists( 'DB' ) ) {
class DB {
// make $cxn a static property shared between instances of this class
private static $cxn = null;
public function __construct() {
$this->connect();
}
private function connect() {
if(!is_null(self::$cxn)) {
// a connection has already been tried, and succeeded
return;
}
self::$cxn = new \mysqli( DB_HOST, DB_USER, DB_PASS, DB_NAME );
if ( self::$cxn->connect_error ) {
die( "Connection failed: " . self::$cxn->connect_errno . ' ' . self::$cxn->connect_error );
}
}