What is the use of the __sleep
and __wakeup
magic methods in PHP? I read the PHP documentation but it's still not clear:
class sleepWakeup { public function __construct() { // constructor // } public function __sleep() { echo 'Time to sleep.'; } public function __wakeup() { echo 'Time to wakeup.'; } } $ob = new sleepWakeup(); // call __sleep method echo $ob->__sleep(); echo "\n"; // call __wakeup method echo $ob->__wakeup();
This sample code prints:
Time to sleep. Time to wakeup.
If I were to rename __sleep
and __wakeup
to foo
and bar
then it does the same thing. What is the proper use of these two methods?
Magic methods in PHP are special methods that are aimed to perform certain tasks. These methods are named with double underscore (__) as prefix. All these function names are reserved and can't be used for any purpose other than associated magical functionality. Magical method in a class must be declared public.
Methods are used to perform actions. In Object Oriented Programming in PHP, methods are functions inside classes. Their declaration and behavior are almost similar to normal functions, except their special uses inside the class.
As already described, __sleep()
is called when you serialize()
an object and __wakeup()
after you unserialize()
it.
Serialization is used to persist objects: You will get a representation of an object as a string that can then be stored in $_SESSION
, a database, cookies or anywhere else you desire.
However, serialize()
cannot serialize (i.e. transform into a textual representation) value sof the resource type. This is why all of these values will go missing after unserialize()
ing it.
or members, and the member's members and the ... ad infinitum
Another, perhaps more important point is, that serialize()
will traverse the entire object graph of $obj
if you serialize it. This is great when you need it, but if you only need parts of the object and certain linked objects are "runtime-specific" and shared across a lot of objects but also by other objects, you may not want that behavior.
PHP handles cyclic graphs correctly! Meaning: If (a member of) $a links to $b, and $b links to $a is handled correctly however many levels deep.
For instance, a $database
object is referenced by $obj->db
, but also by other objects. You will want $obj->db
to be the same objects - after unserialize()
ing - that all the other objects in your next session have, not an isolated instance of the database object.
In this case, you would have __sleep()
method such as this:
/** /* DB instance will be replaced with the one from the current session once unserialized() */ public function __sleep() { unset($this->db); }
and then restore it like this:
public function __wakeup() { $this->db = <acquire this session's db object> }
Another possibility is, that the object is part of some (global) datastructure where it needs to be registered. You could do this manually of course:
$obj = unserialize($serialized_obj); Thing::register($obj);
However, if it is part of the objects contract that it needs to be in that registry, it's not a good idea to leave this magical call up to the user of your object. The ideal solution is, if the object cares about it's responsibilities, i.e. being registered in Thing
. That's what __wakeup()
allows you to do transparently (i.e. he need no longer worry about that magical dependency) to your client.
Similarly, you could use __sleep()
to "un-register" an object if appropriate. (Objects are not destroyed when they're serialized, but it may make sense in your context.)
Last but not least, closures do not support serialization either. This means that you will have to re-create all attached closures in __wakeup()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With