Lazy Instantiation In PHP

Lazy instantiation (also known as lazy load) is an object orientated design pattern that attempts to reduce the amount of resources needed to load an application by only loading certain parts of it if they are needed. This makes sense as you don't need all parts of an application on every page load, so cutting down the data loaded cuts down the resources and processing time needed to load the page.

A good example of this might be when creating a student and courses application or similar. Obviously you would want to link students with their courses, but you don't want to have to load all of the students registered with a course when you are looking at a list of courses. Lazy instantiation allows you to only load the student information when it is called for.

To build this example we will first need a Student class.

class Student
{
  public $studentId;
  public $forename;
  public $surname;
 
  public function Student($studentId, $forename, $surname)
  {
    $this->studentId = $studentId;
    $this->forename = $forename;
    $this->surname = $surname;
  }
 
}

Next we create a Course class. In order to get lazy instantiation we create a $students property and assign it a null value. We also will not do anything in the constructor of the class.

class Course
{
  public $courseId;
  private $students = null;
 
  public function Course($courseId)
  {
    $this->courseId = $courseId;
  }
}

We can now create our Courses object in the normal way.

$course = new Course('111');
print_r($course);

This prints out the following:

Course Object
(
    [courseId] => 111
    [students] => 
)

We would do this every time that we want information about the course, but this class is a bit useless at the moment as there is nothing in place that allows us to get hold of the student information.

This modified version of the Course class adds two functions. The getStudents() is a simple "get" function that returns the $students variable. The only difference is that it first checks to see if the $students variable is null and if so it will run the loadStudents() function to fill the $students variable with the needed data. In the following example this function simply creates two Student objects and puts them into an array, but this function might interface with a database to retrieve the data.

class Course
{
  public $courseId;
  private $students = null;
 
  public function Course($courseId)
  {
    $this->courseId = $courseId;
  }
 
  public function getStudents()
  {
    if ( $this->students == null ) {
      $this->students = $this->loadStudents();
    }
      return $this->students;    
  }
 
  private function loadStudents()
  {
    return array(new Student('1234', 'Jon', 'Doe'),
                 new Student('4321', 'Jane', 'Doe'));
  }
}

We can now run the code that creates the Course object and use the getStudents() function to load the students into the class. The following code allows you to see the state of the Course object before and after lazy instantiation has taken place.

$course = new Course('111');
print_r($course);
 
$students = $course->getStudents();
print_r($course);

This pattern is quite easy to understand and offers a nice way of creating objects when they are needed. It is important to keep an eye on variable scope when writing your programs as if the $student variable is set to public then it is possible to bypass the instantiation step and retrieve a null value.

It is also possible to use the built in PHP __get() function to do the same thing, here is a modified version of the Course class that uses this function.

class Course
{
  public $courseId;
  private $students;
  
  public function Course($courseId)
  {
    $this->courseId = $courseId;
  }
 
  protected function __get($memberName) {
    if ( $memberName == 'students' ) {
      $this->students = $this->loadStudents();
      return $this->students;
    }
  }
 
  private function loadStudents()
  {
    return array(new Student('1234', 'Jon', 'Doe'),
                 new Student('4321', 'Jane', 'Doe'));
  }
}

The $students variable can now be accessed through a simple call to the $students variable of the Courses class. The __get() function will intercept this call and run our lazy instantiation code.

$course = new Course('111');
print_r($course);
$students = $course->students;
print_r($course);

You again need to make sure the $students variable is set to private in order for the __get() function to be run.

Comments

__get function does not return anything and so the output is empty.
Permalink
Fixed.
Name
Philip Norton
Permalink

The example using the __get magic method does not actually lazy load, it always loads.

 

if ( $memberName == 'students' ) { $this->students = $this->loadStudents(); return $this->students; }

 

Thank you for your article.

Permalink

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
16 + 3 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.