【发布时间】:2013-04-16 08:10:49
【问题描述】:
我发现了一个关于 php 析构函数的很奇怪的事情:
基本上我有一个数据库管理类,它使用工厂加载适配器来定义应该加载哪个适配器(mysql、mysqli 等)
我将只写下有趣的部分代码,因为类本身要长得多,但当前的问题不涉及代码
这个问题只发生在 mysql 上(mysqli 和 pdo 工作得很好),但出于兼容性目的,摆脱 mysql 是不可能的。
class manager
{
private static $_instance;
public static function getInstance()
{
return isset(self::$_instance) ? self::$_instance : self::$_instance = new self;
}
public function getStandaloneAdapter()
{
return new mysql_adapter(array('host'=>'127.0.0.1', 'username' => 'root', 'password' => '', 'dbname' => 'etab_21'));
}
}
abstract class abstract_adapter
{
protected $_params;
protected $_connection;
public function __construct($params)
{
$this->_params = (object)$params;
}
public function __destruct()
{
echo 'destructor<br/>';
var_dump(debug_backtrace(false));
$this->closeConnection();
}
abstract public function closeConnection();
}
class mysql_adapter extends abstract_adapter
{
public function getConnection()
{
$this->_connect();
if ($this->_connection) {
// switch database
$this->_useDB($this->_params->dbname);
}
return $this->_connection;
}
protected function _connect()
{
if ($this->_connection) {
return;
}
// connect
$this->_connection = mysql_connect(
$this->_params->host,
$this->_params->username,
$this->_params->password,
true
);
if (false === $this->_connection || mysql_errno($this->_connection)) {
$this->closeConnection();
throw new Mv_Core_Db_Exception(null, Mv_Core_Db_Exception::CONNECT, mysql_error());
}
if ($this->_params->dbname) {
$this->_useDB($this->_params->dbname);
}
}
private function _useDB($dbname)
{
return mysql_select_db($dbname, $this->_connection);
}
public function isConnected()
{
$isConnected = false;
if (is_resource($this->_connection)) {
$isConnected = mysql_ping($this->_connection);
}
return $isConnected;
}
public function closeConnection()
{
if ($this->isConnected()) {
mysql_close($this->_connection);
}
$this->_connection = null;
}
}
这是我正在运行的测试:
$sadb1 = manager::getInstance()->getStandaloneAdapter()->getConnection();
var_dump($sadb1);
我得到的输出:
destructor
array
0 =>
array
'file' => string '**\index.php' (length=48)
'line' => int 119
'function' => string '__destruct' (length=10)
'class' => string 'abstract_adapter' (length=16)
'type' => string '->' (length=2)
'args' =>
array
empty
1 =>
array
'file' => string '**\index.php' (length=48)
'line' => int 119
'function' => string 'unknown' (length=7)
resource(26, Unknown)
如果我把我的测试改成这样:
$sadb1 = manager::getInstance()->getStandaloneAdapter();
var_dump($sadb1->getConnection());
输出不错:
resource(26, mysql link)
destructor
array
0 =>
array
'function' => string '__destruct' (length=10)
'class' => string 'abstract_adapter' (length=16)
'type' => string '->' (length=2)
'args' =>
array
empty
wtf?!
【问题讨论】:
-
出于好奇,为什么
factory函数的第一行是:return new Mv_Core_Db_Adapter_Mysql...?使函数的其余部分变得毫无意义。 -
我已经编辑了我的代码,我已经删除了所有不必要的行并保持最少,仍然无法正常工作 x_x
-
在您的测试期间,除了课程之外,只有这两行用于测试吗?在使用
mysql版本时,您说mysqli和pdo工作正常,在您的代码流中,使用mysql有什么区别?这是一个不寻常的情况,因此在其余代码中的可用性有限? -
由于您从我第一次看到它到您的实际问题大幅削减了代码,+1 为研究工作和一个我以前从未见过的关于垃圾收集过程的好问题. ^^
标签: php mysql destructor fluent-interface