The Sleep and Wakeup Magic Functions in PHP 5

Magic functions are an important part of the numerous improvements and additions that were introduced originally in PHP 5. They can be extremely handy when it comes to simplifying the execution of complex tasks. This is the fourth part of a seven-part series that showcases some of the more useful magic functions and how to implement them.

Ranging from overloading properties and methods of a class, including automatically overloading classes and triggering specific processes before destroying objects, magic functions can be used for doing all sorts of clever things. Some of these have been rather overlooked by many developers, quite possibly because they’re not aware of their full potential.

However, if you’ve been a patient follower of this series of articles and have read all of the preceding tutorials, then you’re familiar with using some of the most relevant magic functions in concrete cases, including the “__set(),” “__get()” and “__call()” trio, and the “__isset()” and “__ unset()” functions as well.

In the last tutorial I explained how to overload a method of a basic class via the aforementioned “__call()” function, which, as you’ll surely recall, is invoked behind the scenes by the PHP engine each time it finds a reference to a non-existent method of a class.

Indeed, method overloading is a powerful approach that allows you to perform complicated tasks with a minimal amount of code, even when this benefit comes at the expense of making the code harder to read and maintain in many cases.

The purpose of this series of article is to explore the most relevant PHP 5 magic functions, so it’s time to talk about the ones that I plan to discuss in the next few lines. So, as this article’s title suggests, in this fourth chapter I’m going to examine closely the “__sleep()” and “__wakeup()” functions, which are called automatically when an object is serialized and unserialized respectively.

By the end of this article, you’ll be armed with the right pointers to start using these functions inside your own PHP applications, so let’s get started. 

{mospagebreak title=Review: the call magic function}

Before demonstrating how to implement and use the “__sleep()” and “__wakeup()” functions when serializing/unserializing objects, I’m going to take an extra step and reintroduce the example developed in the previous installment of this series. It was aimed at illustrating how to overload a single method of a sample class by using the handy “__call()” magic method.

Having explained that, here is the entire source code of the aforementioned example class, which is very simple to follow:

class User

{

// constructor (not implemented)

public function _construct(){}

 

// set undeclared property in a restrictive way

public function __set($property, $value)

{

if (in_array($property, array(‘fname’, ‘lname’, ‘email’)) === TRUE)

{

$this->$property = $value;

}

}

 

// get declared property

public function __get($property)

{

if (isset($this->$property))

{

return $this->$property;

}

}

 

// single point to fetch user data

public function __call($method, $args)

{

if ($method === ‘fetch’ AND empty($args) === FALSE)

{

return $this->$args[0];

}

}

}

As depicted above, the previous “User” class gives a concrete implementation to the “__call()” function, in order to catch all of the calls made to an undeclared “fetch()” method. As you can see, the purpose of this is simply to retrieve the values assigned to the properties of the class by using only this single method.

Finally, to help you understand more clearly how the overloaded “__call()” function does its thing, here’s a short script that shows this process in an approachable fashion. Take a look at it, please:

// example on utilizing ‘User’ class with method overloading

$user = new User();

$user->fname = ‘Alejandro';

$user->lname = ‘Gervasio';

$user->email = ‘alejandro@mydomain.com';

 

// display user data

echo ‘First Name : ‘ . $user->fetch(‘fname’) . ‘ Last Name : ‘ . $user->fetch(‘lname’) . ‘ Email : ‘ . $user->fetch(‘email’);

 

/*

display the following

First Name : Alejandro Last Name : Gervasio Email : alejandro@mydomain.com

*/

See how simple it is to overload methods in PHP 5? I bet you do! In this particular case, even when the “fetch()” method hasn’t been declared within the “User” class, each time the script calls it, it’ll be intercepted by the “__call()” function, in this way avoiding the triggering of a fatal error.

So far, so good. At this stage, you hopefully recalled how to use the “__call()” magic function to recreate a simple case of method overloading. Therefore, it’s time to explore other magic functions.

So, as I explained at the beginning, in the section to come I’m going to discuss how to use the “__sleep()” and “__wakeup()” functions when serializing and unserializing objects.

To learn more on this topic, now click on the link below and keep reading.

{mospagebreak title=Introducing the sleep and wakeup functions}

As I explained in the introduction, PHP 5 also includes a pair of complementary magic functions called “__sleep()” and “__wakeup(),” which are transparently invoked when an object is being serialized and unserialized respectively.

In theory, these functions should be very easy to grasp, but it’d be even better to back up these concepts with some illustrative examples. So, below I redefined the “User” class that you saw before by giving a basic implementation to the “__sleep()” and “__wakeup()” methods.

Take a look at the class’s source code, which now looks like this:

class User

{

// constructor (not implemented)

public function _construct(){}

 

// set undeclared property in a restrictive way

public function __set($property, $value)

{

if (in_array($property, array(‘fname’, ‘lname’, ‘email’)) === TRUE)

{

$this->$property = $value;

}

}

 

// get declared property

public function __get($property)

{

if (isset($this->$property))

{

return $this->$property;

}

}

 

// single point to fetch user data

public function __call($method, $args)

{

if ($method === ‘fetch’ AND empty($args) === FALSE)

{

return $this->$args[0];

}

}

 

// implement __sleep() method

public function __sleep()

{

echo ‘Serializing user object';

return array(‘fname’);

}

 

// implement __wakeup() method

public function __wakeup()

{

echo ‘Unserializing user object';

}

}

Now, apart from using the already familiar “__call()” function, the above “User” class also gives a concrete implementation of the “__sleep()” and “__wakeup()” methods. It’s admittedly very trivial, since they’ll only display a message on the browser when being called by the PHP engine. Despite the simplicity of this particular example, it should be useful enough to demonstrate how to utilize the “__sleep()” and “__wakeup()” functions within a class.

However, the “User” class itself won’t do anything useful until an instance of it is serialized or unserialized, since the mentioned magic methods will be called upon the occurrence of these specific events.

So, it’s necessary to create a script that performs these tasks in a simple manner. Thus, in the last section of this tutorial I’m going to develop a wrapping example that will show what happens when an instance of the previous “User” class in serialized and unserialized sequentially.

To learn how this final example will be created, click on the link that appears below and read the following section.

{mospagebreak title=The sleep and wakeup methods in action}

The best way to understand how the previously implemented “__sleep()” and “__wakeup()” magic methods do their business is by means of a concrete example that uses the “serialize()” and “unserialize()” PHP functions with an instance of the previous “User” class.

Based on this idea, below I created a simple script that performs this serialization/unserialization process in an approachable fashion. Look at it, please:

// example on using the ‘User’ class with the ‘__sleep()’ and ‘__wakeup()’ methods

 

$user = new User();

$user->fname = ‘Alejandro';

$user->lname = ‘Gervasio';

$user->email = ‘alejandro@mydomain.com';

// display user data

echo ‘First Name : ‘ . $user->fetch(‘fname’) . ‘ Last Name : ‘ . $user->fetch(‘lname’) . ‘ Email : ‘ . $user->fetch(‘email’);

/*

displays the following

First Name : Alejandro Last Name : Gervasio Email : alejandro@mydomain.com

*/

 

// serialize user object

$user = serialize($user);

/*

displays the following

Serializing user object

*/

 

// unserialize user object

var_dump(unserialize($user));

/*

displays the following

object(User)[1]

public ‘fname’ => string ‘Alejandro’ (length=9)

*/

As you can see in the above script, each time an instance of the previous “User” class is serialized and unserialized, the PHP engine calls internally the “__sleep()” and “__wakeup()” methods, which display a simple message on the browser. Of course, it’s possible to give a more useful and complex implementation of these methods, but hopefully the code sample shown above will give you a more clear idea of how to do this all by yourself.

Feel free to tweak all of the examples shown in this tutorial, so you can arm yourself with a better grounding in using these magic functions in PHP 5.

Final thoughts

That’s it for now. In this fourth chapter of the series I provided you with a brief introduction to using the “__sleep()” and “__wakeup()” magic functions when serializing and unserializing objects.

Logically, as I said before it’s possible to implement these functions in a more useful way, for instance for creating persistent objects that save themselves to a file or a database when they’re serialized. Indeed, the possibilities are pretty numerous.

In the next article, I’m going to continue this exploration of magic functions that come with PHP 5. That particular tutorial will be focused on discussing the “__clone()” function.

Don’t miss the upcoming part!

[gp-comments width="770" linklove="off" ]

chat