php mysql 1040_php – 如何修复消息:SQLSTATE [08004] [1040]连接太多

因为您的Model类在其构造函数中实例化一个新的Database对象,所以每次实例化一个Model(或任何扩展它的类)时,您实际上都在打开一个新的数据库连接.如果你创建了几个Model对象,那么每个对象都有自己独立的数据库连接,这种连接不常见,通常是不必要的,不能很好地利用资源,但是由于它耗尽了所有服务器的可用连接,因此也是有害的.

例如,循环以创建Model对象的数组:

// If a loop creates an array of Model objects

while ($row = $something->fetch()) {

$models[] = new Model();

}

// each object in $models has an independent database connection

// the number of connections now in use by MySQL is now == count($models)

使用依赖注入:

解决方案是使用依赖注入并将Database对象传递给Model :: __ construct(),而不是允许它实例化它自己的.

class Model {

protected $_db;

// Accept Database as a parameter

public function __construct(Database $db) {

// Assign the property, do not instantiate a new Database object

$this->_db = $db;

}

}

然后,使用它,控制代码(将实例化您的模型的代码)本身应该只调用一次新的Database().然后,必须将控制代码创建的对象传递给所有模型的构造函数.

// Instantiate one Database

$db = new Database();

// Pass it to models

$model = new Model($db);

对于您实际需要为模型使用不同的独立数据库连接的用例,您可以将其交给另一个.特别是,这对测试很有用.您可以替换测试数据库对象或模拟对象.

// Instantiate one Database

$db = new Database();

$another_db = new Database();

// Pass it to models

$model = new Model($db);

$another_model = new Model($another_db);

持久连接:

正如评论中所提到的,使用持久连接可能是一种解决方案,但不是我建议的解决方案. PDO将尝试重用具有相同凭据的现有连接(与您的所有连接一样),但您不一定希望跨脚本执行缓存连接.如果您决定以这种方式执行此操作,则需要将该属性传递给Database构造函数.

try {

// Set ATTR_PERSISTENT in the constructor:

parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS, array(PDO::ATTR_PERSISTENT => true));

$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");

}

单身解决方案:

使用单例模式(也不推荐),您至少可以将其减少为模型代码中的搜索/替换. Database类需要一个静态属性来保持自身的连接.然后模型调用Database :: getInstance()而不是新的Database()来检索连接.您需要在Model代码中进行搜索和替换以替换Database :: getInstance().

虽然它运行良好并且不难实现,但在您的情况下,它会使测试更加困难,因为您必须使用同名的测试类替换整个Database类.您不能轻易地在实例的基础上替换测试类.

将单例模式应用于数据库:

class Database extends PDO{

// Private $connection property, static

private static $connection;

// Normally a singleton would necessitate a private constructor

// but you can't make this private while the PDO

// base class exposes it as public

public function __construct(){

try {

parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);

$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");

} catch(PDOException $e){

Logger::newMessage($e);

logger::customErrorMsg();

}

}

// public getInstance() returns existing or creates new connection

public static function getInstance() {

// Create the connection if not already created

if (self::$connection == null) {

self::$connection = new self();

}

// And return a reference to that connection

return self::$connection;

}

}

现在,您只需要更改Model代码即可使用Database :: getInstance():

class Model {

protected $_db;

public function __construct(){

// Retrieve the database singleton

$this->_db = Database::getInstance();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值