Lazy Loading Resources in PHP
In most PHP applications it is common to have several resources. The database connection, the user session, the server-side cache object and helper classes are eventually used in parts of the application. But often times, certain pages do not need all of the resources. In this tutorial, I'll show you how to use lazy loading to create the resources only when you need them.
What is Lazy Loading?
Lazy loading is based on the concept that your resources should only be created when needed, and re-used if needed more than once. It's fairly straight-forward to implement and can also help with unit tests (more on this later).
How Lazy Loading Works
Lazy loading works best in object-oriented code, so we'll begin with a class. Let's say we're building a simple database connection class and want to lazy load the actual connection. A typical class might look like this:
<?php
class DbConnection
{
protected $_connection;
public function __construct($dsn, $username = null, $password = null, array $options = array())
{
$this->_connection = new Pdo($dsn, $username, $password, $options);
}
public function getConnection()
{
return $this->_connection;
}
}
As you can see, the connection to the database is made immediately when the DbConnection class is instantiated. Normally this type of object is created in the application's bootstrap so that all pages will have access to a database connection.
But what happens when you have a page that doesn't need a database connection? That resource is now wasted CPU cycles. How can this be improved by lazy loading?
Simple -- just move the connection code into the getConnection() method. You can then test if the connection has already been made and, if not, create a new one. Keep in mind that you'll also need to store the constructor arguments so that they are available when you need to make the connection.
<?php
class DbConnection
{
protected $_connection;
protected $_dsn;
protected $_username;
protected $_password;
protected $_options = array();
public function __construct($dsn, $username = null, $password = null, array $options = array())
{
$this->_dsn = $dsn;
$this->_username = $username;
$this->_password = $password;
$this->_options = $options;
}
public function getConnection()
{
if (null === $this->_connection) {
$this->_connection = new Pdo($this->_dsn, $this->_username, $this->_password, $this->_options);
}
return $this->_connection;
}
}
Now your database connection won't be opened until you call DbConnection::getConnection(). This can help improve overall application performance if many of your pages do not require a database connection.
Unit Testing with Lazy Loading
Lazy loading compliments unit-testing because you can stub in a mock connection before calling DbConnection::getConnection(), allowing you to test your application without the need of a real database connection.
This is as simple as adding a setConnection() method:
<?php
class DbConnection
{
/* ... */
public function setConnection(Pdo $connection)
{
$this->_connection = $connection;
}
}
What else is Lazy Loading good for?
Lazy loading isn't just for database connections. Virtually any resource can be lazy-loaded to help improve performance. For example, I use lazy loading often in my Zend Framework applications to load things like forms, table classes, and service layers.
The way I see it, there's no need to load a service if it's not going to be used, and there's no need to load the same service more than once when the same instance will do.
0 Comments
Post a comment!
- No comments yet. Be the first to comment on this blog entry!
