Php 为什么可以';不能序列化PDO对象吗?
我正在制作一个多线程CLI-PHP应用程序,需要序列化Php 为什么可以';不能序列化PDO对象吗?,php,pdo,Php,Pdo,我正在制作一个多线程CLI-PHP应用程序,需要序列化PDO对象,以便在线程内部的工作之间传递它,并使用神奇的方法\uuu sleep()和\uu wakeup()将它从休眠线程中唤醒。但是,PDO或mysqli扩展也不支持它。旧的mysql_*()api实现了这一点,但它已被弃用并删除 <?php // Application $link = new PDO('mysql:host=localhost;port=3306;dbname=testdatabase', 'ro
PDO对象
,以便在线程内部的工作之间传递它,并使用神奇的方法\uuu sleep()
和\uu wakeup()
将它从休眠线程中唤醒。但是,PDO
或mysqli
扩展也不支持它。旧的mysql_*()
api实现了这一点,但它已被弃用并删除
<?php
// Application
$link = new PDO('mysql:host=localhost;port=3306;dbname=testdatabase', 'root', '');
$obj = serialize($link);
PDO对象包含无法以序列化格式表示的状态。例如,PDO对象包含到数据库服务器的开放连接
如果要尝试反序列化序列化的PDO对象,则必须将\u wakeup()
方法重新连接到数据库服务器。这将要求身份验证凭据以可读的方式存储在序列化PDO对象中,这是一个安全问题
很久以前我就在研究Zend Framework的Zend_Db组件,出于这个原因,我特意将Zend_Db_适配器对象设计为不可序列化。Zend_Db_Table、Zend_Db_Table_Row等的实例可以序列化,但在反序列化后不能“活动”,直到您为其分配了一个新连接的Zend_Db_适配器实例
此外,也不能保证在反序列化PDO对象时可以访问数据库服务器。目前尚不清楚这是否意味着反序列化将被视为“失败”
对序列化的相同限制也适用于其他资源,如套接字或文件句柄
另请参见正在创建一个可序列化的包装器,因为PDO链接本身无法序列化
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
}?>
PDO对象显然没有在连接后保留dsn、user、pwd,因此无法直接序列化。但是,如果像上面的示例中那样创建了一个包装器,在其中存储了这些信息,则可以序列化包装器。然后,当您取消序列化时,它将创建一个新的PDO对象,并通过将凭证从包装器传递到PDO来重新连接。序列化只捕获超常规的PDO对象属性(其中没有太多),但不是幕后的套接字连接和缓冲区等。这不是重复的问题,因为接受的答案没有回答任何问题@马里奥同意。答案无法解释PDO无法序列化的原因,它只是使用循环推理(您无法序列化无法序列化的对象。
)。我觉得正确的答案应该是->,因为会话数据是序列化的,资源变量不能存储在会话中。
。所以,因为PDO是一个外部资源,它不能被序列化。我真的怀疑除了“序列化数据库连接没有意义”之外,还有什么解释可以给出。也许是OP解释了他为什么要首先进行serlise…嘿,Bill,只是一个想法:是否有任何有趣的东西可以使用反射类/方法从PDO实例中提取(其他情况下不提供的信息)?@DanFromGermany:您可以使用ReflectionObject::export($PDO)
来测试这一点。反射只访问可以通过PHP访问的公共和私有常量、属性和方法。不是PDO扩展内部的任何部分。你看起来像是在私营部门工作而不是为政府工作的人。