我发现关于 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
哇?!