A Magical Lullaby
When you want to take control over the state of your objects as they're serialized, PHP provides two magical functions to help you. As the documentation states:
Unfortunately, there's one gotcha that severely limits the usefulness of this magic. Unless the __sleep method returns an array of the member names that you want serialized, the entire object gets serialized as null. This requirement is not only contradictory to the stated "intended use", it's nearly impossible to satisfy.
To explore this further, consider the example given in the documentation: a simple database wrapper. Now I'm not really sure why you'd want to serialize a database connection, but we'll assume you have to. You can't actually serialize the underlying resource that the connection is using, so you'll need to disconnect it before serialization occurs. That's all we need the __sleep method to do.
We could -- like the example -- disconnect and return a hard-coded list of our properties. Maintenance hell. So let's write a function that will properly build a list of all the properties (public, protected, AND private) in a child and all its ancestors.
What a nightmare, and just to close a connection. That's why I created a patch that will allow __sleep to return NULL, in which case the object is serialized as usual. You can find it (for the PHP_5_3 branch and HEAD) attached to my message to the internals list. Let's hope it gets committed.
The intended use of __sleep is to commit pending data or perform similar cleanup tasks. Also, the function is useful if you have very large objects which do not need to be saved completely. Conversely, [...] the intended use of __wakeup is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.
Unfortunately, there's one gotcha that severely limits the usefulness of this magic. Unless the __sleep method returns an array of the member names that you want serialized, the entire object gets serialized as null. This requirement is not only contradictory to the stated "intended use", it's nearly impossible to satisfy.
To explore this further, consider the example given in the documentation: a simple database wrapper. Now I'm not really sure why you'd want to serialize a database connection, but we'll assume you have to. You can't actually serialize the underlying resource that the connection is using, so you'll need to disconnect it before serialization occurs. That's all we need the __sleep method to do.
We could -- like the example -- disconnect and return a hard-coded list of our properties. Maintenance hell. So let's write a function that will properly build a list of all the properties (public, protected, AND private) in a child and all its ancestors.
<?php
class Connection {
[...]
public function __sleep()
{
mysql_close($this->link);
return $this->getPropertyNames();
}
public function getPropertyNames(array $filter = NULL)
{
$rc = new ReflectionObject($this);
$names = array();
while ($rc instanceof ReflectionClass)
{
foreach ($rc->getProperties() as $prop)
{
if (!$filter || !in_array($prop->getName(), $filter))
$names[] = $prop->getName();
}
$rc = $rc->getParentClass();
}
return $names;
}
[...]
}
?>
What a nightmare, and just to close a connection. That's why I created a patch that will allow __sleep to return NULL, in which case the object is serialized as usual. You can find it (for the PHP_5_3 branch and HEAD) attached to my message to the internals list. Let's hope it gets committed.
