Before I begin demonstrating how to improve the efficiency of the sample script developed in the previous installment of the series by applying the concept of lazy loading, it would be helpful to reintroduce the full source code of that particular example as a review. Below you'll find the definition of the class that is eagerly loaded by the aforementioned script, which actually does nothing except store data about some hypothetical users. Here it is: 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 functionality of the above "User" class is limited to storing information about a particular user via its "fname," "lname" and "email" properties, which also can be retrieved thanks to the implementation of the corresponding getter methods. However, since the logic of this class is very easy to follow, I'm not going to waste more time explaining how it functions. Instead, it's time to go one step further and show the source code of a loader module that will be used at a later time for including the "User" class. Here's the definition of this simple module: // create custom FileNotFoundException exception class class FileNotFoundException extends Exception {}
// create custom ClassNotFoundException exception class class ClassNotFoundException extends Exception {}
// 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.'); } } } Basically, all that this module does is include on demand a specified class via a PHP require. In addition, it defines a couple of exception subclasses to throw custom exceptions when attempting to load a certain class. You should have no trouble understanding this process. Finally, here's the script that uses the functionality of the previous loader module to eagerly include the "User" class shown previously. Look at it, please: try { // load eagerly 'User' class Loader::load('user'); /* rest of logic goes here */ // create instance of 'User' class $user = new User('Mary', 'Smith', 'mary@domain.com'); echo $user; } catch (FileNotFoundException $e){ echo $e->getMessage(); exit(); }
catch (ClassNotFoundException $e){ echo $e->getMessage(); exit(); } If you ask yourself what's the big deal with this script, my answer would be simply ...nothing. However, the script actually does do something that deserves a closer look. As you can see, at the very beginning it calls the static "load()" method that belongs to "Loader" to include the "User" class, even though an instance of it is only created when the script finishes its execution. This shows in a nutshell the logic that stands behind using the eager loading pattern, which in this particular example is applied to include a basic class. Though, as I said in the introduction, eager loading can be utilized in many different cases, such as instantiating classes, prefetching database rows, and so forth. In the previous example, eager loading causes a detriment to the performance of the sample script, since the class is loaded first, without taking into account whether or not an instance of it will be required. The question that brings up here is, can this issue be fixed with only minor hassles? Fortunately, the answer is yes! By applying the opposite pattern, that is lazy loading, it's possible to rewrite the previous script so it can load the "User" class if and only if it's requested at runtime. Want to learn how this can be accomplished in a few steps? Then click on the link that appears below and read the section to come.
blog comments powered by Disqus |
|
|
|
|
|
|
|