Why can't a PDO be serialized?

I am making a multi-threaded CLI-PHP application and have to serialize a PDO object in order to pass it between work inside the thread and wake it from the sleeping thread using the magic methods __sleep() and __wakeup() . However, it does not support the PDO or mysqli extension. The old mysql_*() api did this, but it is deprecated and deleted.

 <?php // Application $link = new PDO('mysql:host=localhost;port=3306;dbname=testdatabase', 'root', ''); $obj = serialize($link); 

generate error

PHP Fatal error: throw a "PDOException" exception with the message "You cannot initialize or unesterialize PDO instances in W: \ workspace \ Sandbox \ application.php: 5 Stack trace:

# 0 [internal function]: PDO β†’ __ sleep ()

# 1 W: \ workspace \ Sandbox \ application.php (5): serialize (Object (PDO))

# 2 {main} thrown at W: \ workspace \ Sandbox \ application.php on line 5

+3
source share
2 answers

The PDO contains a state that cannot be represented in serialization format. For example, a PDO contains an open connection to a database server.

If you try to deserialize a serialized PDO, the __wakeup() method will need to reconnect to the database server. This will require that the authentication credentials be stored in a readable form in a serialized PDO, which is a no-no security.

I have been working on the Zend Framework component Zend_Db for a long time, and I specially designed the Zend_Db_Adapter object so that for this reason it would not be serializable. Instances of Zend_Db_Table, Zend_Db_Table_Row, etc. They can be serializable, but they cannot be β€œlive” after deserialization, until you assign a newly connected instance of Zend_Db_Adapter to it.

In addition, there is no guarantee that the database server will be available at the time of deserialization of the PDO. It is unclear whether this means that deserialization will be considered "unsuccessful."

The same serialization restrictions apply to other resources, such as sockets or file descriptors.

See also Why not every type of serializable object?

+9
source

What is being done at http://php.net/manual/en/language.oop5.magic.php creates a wrapper that can be serialized because the PDO link itself cannot be.

 <?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(); } }?> 

The PDO object does not seem to support dsn, user, pwd after connection, and therefore cannot be directly serialized. But if you created a wrapper, as in the example above, where you saved this information, you can serialize the shell. Then, when you are not serializing, it will create a new PDO object and reconnect, passing the credentials from the shell to the PDO.

+1
source