为什么不能序列化 PDO 对象?
我正在制作一个多线程 CLI-PHP 应用程序,需要序列化 PDO 对象
以在线程内部的工作之间传递它,并使用魔术方法将其从睡眠线程中唤醒 __sleep()
和 __wakeup()
.然而,PDO
或 mysqli
扩展也不支持它.旧的 mysql_*()
api 做到了这一点,但它已被弃用和删除.
I am making a multi-threaded CLI-PHP application and need to serialize PDO object
to pass it between work inside the thread, and wake it up from a sleeping thread using magic methods __sleep()
and __wakeup()
. However nor the PDO
or mysqli
extension supports it. The old mysql_*()
api did this but it has been deprecated and removed.
<?php
// Application
$link = new PDO('mysql:host=localhost;port=3306;dbname=testdatabase', 'root', '');
$obj = serialize($link);
产生错误
PHP 致命错误:未捕获的异常 'PDOException' 带有消息 'You无法序列化或反序列化 PDO 实例W:workspaceSandboxapplication.php:5 堆栈跟踪:
PHP Fatal error: Uncaught exception 'PDOException' with message 'You cannot ser ialize or unserialize PDO instances' in W:workspaceSandboxapplication.php:5 Stack trace:
#0 [内部函数]:PDO->__sleep()
#0 [internal function]: PDO->__sleep()
#1 W:workspaceSandboxapplication.php(5): 序列化(Object(PDO))
#1 W:workspaceSandboxapplication.php(5): serialize(Object(PDO))
#2 {main} 在第 5 行的 W:workspaceSandboxapplication.php 中抛出
#2 {main} thrown in W:workspaceSandboxapplication.php on line 5
推荐答案
PDO 对象包含无法以序列化格式表示的状态.例如,PDO 对象包含一个到数据库服务器的开放连接.
A PDO object contains state that cannot be represented in the serialization format. For example, the PDO object contains an open connection to a database server.
如果您尝试反序列化一个序列化的 PDO 对象,__wakeup()
方法必须重新连接到数据库服务器.这将要求身份验证凭证以可读方式存储在序列化 PDO 对象中,这是安全禁忌.
If you were to try to deserialize a serialized PDO object, the __wakeup()
method would have to reconnect to the database server. This would require that authentication credentials be stored in a readable manner in the serialized PDO object, which is a security no-no.
我很早以前就在研究 Zend Framework 的 Zend_Db 组件,因此我特意将 Zend_Db_Adapter 对象设计为不可序列化.Zend_Db_Table、Zend_Db_Table_Row 等的实例可以序列化,但在反序列化后不能活动",除非你为它分配了一个新连接的 Zend_Db_Adapter 实例.
I worked on the Zend Framework's Zend_Db component a long time ago, and I deliberately designed the Zend_Db_Adapter object to not be serializable for this reason. Instances of Zend_Db_Table, Zend_Db_Table_Row, etc. could be serializable, but could not be "live" after deserialization until you assigned it a freshly connected Zend_Db_Adapter instance.
此外,无法保证在您反序列化 PDO 对象时可以访问数据库服务器.目前尚不清楚这是否意味着反序列化将被视为失败".
Also, there's no guarantee that the database server would be reachable at the time you deserialize the PDO object. It's unclear whether this means the deserialization would be considered "failed."
对序列化的相同限制适用于其他资源,例如套接字或文件句柄.
The same restrictions on serialization apply to other resources such as sockets or file handles.
另见 为什么不是每种类型的对象都可序列化?
相关文章