Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/240.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 为什么可以';不能序列化PDO对象吗?_Php_Pdo - Fatal编程技术网

Php 为什么可以';不能序列化PDO对象吗?

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

我正在制作一个多线程CLI-PHP应用程序,需要序列化
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扩展内部的任何部分。你看起来像是在私营部门工作而不是为政府工作的人。