Lazy and Eager Loading with Object Properties

Welcome to the fourth chapter of this series on implementing lazy and eager loading in PHP 5. In five friendly tutorials, this series walks you through the basics of using these powerful approaches for including classes on request in your scripts, and teaches you how to work with these patterns when manipulating properties of a certain class.

Without a doubt, grasping the key concepts that surround the implementation of the lazy and eager loading design patterns in PHP 5 can be of great help when it comes to developing web-based applications that handle their resources in a truly efficient way.

So, if you’re a PHP programmer who wants to expand your existing skills by learning how to apply the aforementioned patterns in some concrete cases, then don’t look any further, because you’ve come to the right place.

And now that you’re aware of the objective of this group of tutorials, it’s time to review briefly the concepts that were deployed in the previous article. In that installment of this series I demonstrated how to take advantage of the functionality given by lazy loading to include a basic class only when a script really required it. Not earlier, and not later neither.

This was accomplished thanks to the development of a resource-loader module, which exploited the nifty autoloading capabilities offered by PHP 5 to include the mentioned class on demand.

However, as I stated in earlier chapters of the series, lazy and eager loading can be used in multiple scenarios and situations, naturally with different results. So, in this fourth episode I’m going to explain how to utilize the eager loading pattern when handling the properties declared by the same “User” class that you learned in the previous tutorial.

Want to find out how this will be achieved in a few simple steps? Then begin reading right now!

{mospagebreak title=Review: using the lazy loader pattern with PHP 5} 

If you still haven’t had the chance to read the preceding installment of this series, where I explained how to use lazy loading for including a sample class into a script only when it was really required, don’t worry. In the following lines I reintroduced the full source code corresponding to this example, so you can quickly grasp its underlying logic.

First, here’s the definition of the class that needs to be included on demand. In this case, it’s tasked with storing some user-related data through its declared properties:

class User {

 

private $fname = ‘Alejandro';

private $lname = ‘Gervasio';

private $email = ‘alejandro@mydomain.com';

 

public function __construct($fname = ”, $lname = ”, $email = ”)

{

if (is_string($fname) and !empty($fname))

{

$this->fname = $fname;

}

if (is_string($lname) and !empty($lname))

{

$this->lname = $lname;

}

if (is_string($email) and !empty($email))

{

$this->email = $email;

}

}

 

// get user’s first name

public function getFirstName()

{

return $this->fname;

}

 

// get user’s last name

public function getLastName()

{

return $this->lname;

}

 

// get user’s email

public function getEmail()

{

return $this->email;

}

 

// display user data

public function __toString()

{

return ‘First Name: ‘ . $this->fname . ‘<br />Last Name: ‘ . $this->lname . ‘<br />Email: ‘ . $this->email;

}

}

As I mentioned before, the above “User” class in reality does nothing especially useful, except storing the first and last names, as well as the email address, of a particular user via three properties whose values can be retrieved through the corresponding getter methods.

Now that you understand the internal workings of the previous “User” class, it’s time to show the definition of the loader module, which is responsible for including this class into a calling script on request.

The module in question looks as follows:

// create custom FileNotFoundException exception class

class FileNotFoundException extends Exception {}

 

// create custom ClassNotFoundException exception class

class ClassNotFoundException extends Exception {}

 

spl_autoload_register(array(‘Loader’,’load’));

 

// define ‘Loader’ class

class Loader {

 

public static function load($class)

{

if (class_exists($class, FALSE))

{

return;

}

$file = $class . ‘.php';

if(!file_exists($file))

{

throw new FileNotFoundException(‘File ‘ . $file . ‘ not found.’);

}

require $file;

unset($file);

if (!class_exists($class, FALSE))

{

eval(‘class ‘ . $class . ‘{}’);

throw new ClassNotFoundException(‘Class ‘ . $class . ‘ not found.’);

}

}

}

Aside from creating a couple of subclasses that extend the default Exception class provided by PHP 5, this loader module defines a basic auoloading mechanism for including a specific class into a script if and only if it’s required by that script.

Of course, if you study closely the rationale that stands behind the loader module, then you’ll realize that it’s actually the component that permits it to implement lazy loading in a few simple steps. However, to dissipate your possible doubts, below there’s a script that uses this module for lazily-loading the earlier “User” class:

// create instance of ‘User’ class only when the script requires it

try {

// create instance of ‘User’ class

$user = new User();

echo $user;

}

catch (FileNotFoundException $e){

echo $e->getMessage();

exit();

}

 

catch (ClassNotFoundException $e){

 echo $e->getMessage();

exit();

}

There you have it. As the previous code sample shows, the “User” class is only included into the calling script when it’s really required, thanks to the functionality of the loader module shown before.

So far, so good. Now that you realized that applying the lazy loading pattern in PHP 5 is much easier than you might think, it’s time explore other situations where this pattern, and its counterpart, eager loading, can be applied with different levels of success.

It’s quite possible that by the time you looked at the sample “User” class, you noticed that it implements eager loading in a pretty basic way. But, in which part of the class does this take place? Well, the answer to this question is really obvious, but if you need a complete explanation of this mysterious thing, then click on the link below and read the following section.

{mospagebreak title=Simple eager loading: examining the user class}

As I stated at the beginning of this series of articles, both lazy and eager loading patterns can be applied in diverse scenarios and contexts with distinct results. It’s also valid to mention that there are cases where they’re used by some developers who aren’t completely aware of what they’re really doing.

To demonstrate this concept a bit more clearly, take a closer look (and when I say closer, I mean really CLOSER) at the definition of the sample “User” class shown in the previous segment:

class User {

 

private $fname = ‘Alejandro';

private $lname = ‘Gervasio';

private $email = ‘alejandro@mydomain.com';

 

public function __construct($fname = ”, $lname = ”, $email = ”)

{

if (is_string($fname) and !empty($fname))

{

$this->fname = $fname;

}

if (is_string($lname) and !empty($lname))

{

$this->lname = $lname;

}

if (is_string($email) and !empty($email))

{

$this->email = $email;

}

}

 

// get user’s first name

public function getFirstName()

{

return $this->fname;

}

 

// get user’s last name

public function getLastName()

{

return $this->lname;

}

 

// get user’s email

public function getEmail()

{

return $this->email;

}

 

// display user data

public function __toString()

{

return ‘First Name: ‘ . $this->fname . ‘<br />Last Name: ‘ . $this->lname . ‘<br />Email: ‘ . $this->email;

}

}

If I ever have to make a list of basic classes that I’ve built so far, then the above “User” class would be at the top of that list. So, what’s the unrevealed thing that could be hidden behind its trivial definition? Well, in this case the class assigns default values for its three properties, in case that its constructor gets called with no input arguments.

But if you analyze this process in depth, what it’s actually doing is eagerly assigning those values to the properties, regardless of whether or not they’ll be used later. Now, in a situation like this the class would be applying the eager loading pattern to its set of properties, even when in programming jargon this task is commonly known as property initialization. This demonstrates that even a class as basic as “User” also can take advantage of eager loading to prevent possible errors, when attempting to retrieve its properties via its public API.

Despite the fact that grasping the implementation of the eager loading pattern within the “User” class is a breeze, it’d be useful to create a script that shows the real benefits of this process. So, in the final section of this article I’m going to build that script for you.

To learn more, read the following segment.

{mospagebreak title=Applying eager loading to an instance of the User class}

The best way to understand how the eager loading pattern is used by the sample “User” class is simply by coding a script that creates an instance of it without passing any incoming parameters to its constructor.

The code sample that does that is the following, provided that the class in question has been saved to a file called “user.php”:

require_once ‘user.php’

// create instance of ‘User’ class

$user = new User();

// display user data

echo $user;

If you run this script on your own web server, the you’ll see that it outputs to screen the default values assigned to the “User” class properties, once an instance of it is created. This naturally happens due to the call to the magic “__toString()” method, but you’ll get a non-empty result when invoking any of its getter methods as well.

While extremely simplistic, this example demonstrates that it’s possible to implement eager loading at lower levels and exploit its eventual benefits, even when in some cases these may be negligible.

Feel free to edit all of the examples developed in this tutorial. Doing this surely will arm you with a better knowledge of eager loading in PHP 5.

Final thoughts  

In this fourth installment of the series, I demonstrated through a simple example that it’s feasible to implement the eager loading pattern with the properties of a basic class. Nonetheless, the experience would be incomplete if I don’t show you how to apply lazy loading to the properties of the same class.

That will be exactly the subject that I plan to discuss in the final part of this series, so I recommend that you not miss it!

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

chat