Use of PHP Magic Methods __sleep and __wakeup

Viewed 33217

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?

5 Answers

Since PHP 7.4 there will be new methods __serialize() and __unserialize() available which should slightly change the usage of __sleep and __wakeup magic methods.

PHP currently provides two mechanisms for custom serialization of objects: The __sleep()/__wakeup() magic methods, as well as the Serializable interface. Unfortunately, both approaches have issues that will be discussed in the following. This RFC proposes to add a new custom serialization mechanism that avoids these problems.

More in PHP RFC manual https://wiki.php.net/rfc/custom_object_serialization.

// Returns array containing all the necessary state of the object.
public function __serialize(): array;

// Restores the object state from the given data array.
public function __unserialize(array $data): void;

The usage is very similar to the Serializable interface. From a practical perspective the main difference is that instead of calling serialize() inside Serializable::serialize(), you directly return the data that should be serialized as an array.

The following example illustrates how __serialize()/__unserialize() are used, and how they compose under inheritance:

class A {
    private $prop_a;
    public function __serialize(): array {
        return ["prop_a" => $this->prop_a];
    }
    public function __unserialize(array $data) {
        $this->prop_a = $data["prop_a"];
    }
}
class B extends A {
    private $prop_b;
    public function __serialize(): array {
        return [
            "prop_b" => $this->prop_b,
            "parent_data" => parent::__serialize(),
        ];
    }
    public function __unserialize(array $data) {
        parent::__unserialize($data["parent_data"]);
        $this->prop_b = $data["prop_b"];
    }
}

This resolves the issues with Serializable by leaving the actual serialization and unserialization to the implementation of the serializer. This means that we don't have to share the serialization state anymore, and thus avoid issues related to backreference ordering. It also allows us to delay __unserialize() calls to the end of unserialization.

Related