Lazy Loading Resources with Zend Framework Bootstrap

The Bootstrapping process in Zend Framework isn’t perfect. You’ll often end up bootstrapping a lot of resources that you don’t need to complete the request. Depending on the resources this can be really expensive and hurt your overall performance.

The worst kind are resources that open connections to external services like MySQL and Memcached. Both Memcache::connect() and MySQLi::__construct() will try to connect to the server immediately and this can, and usually will be, “slow”. Even worse, if the services are down they will end up blocking the execution.

An initialization of a memcache resource would typically look something like this:

If your Memcached server is down this will end up blocking the entire application, even if you don’t actually use the resource.

Solve it with lazy loading!

The solution to these problems is lazy loading. The following two methods provides an easy, efficient and small implementation of lazy loading that can be used in almost any Zend Framework bootstrap.

The usage of these methods is quite easy and only requires small changes to your existing resource initialization methods. If we want to add lazy loading to the memcache initialization method above, it can be accomplished like this:

This will defer the creation of the Memcache object until someone actually performs a $bootstrap->getResource('memcache'); and therefore the connection will only be made when actually needed.

In-depth explanation of how this works.

The lazyload() method wraps your normal initialization, which is passed in as the anonymous function $callable, inside an anonymous function. This wrapper function contains a static $object variable which is unique to the created instance of the function. The first time this anonymous function is executed $object will be null and $callable will be executed, the result of calling $callable will be stored in $object. This makes sure you only initialize the resource once.

Just implementing lazyload() would cause getResource() to return a Closure object, containing the anonymous wrapper function. That is little use to us in our code so we extend the getResource() method as well. Our getResource() method checks if the requested resource is callable and then call it.

The entire code for this example is located in this gist.

Read more from the Software engineering category