Automatic caching of Zend_Db (or any object) calls

I’m working on a personal Zend framework application that uses Zend_Db_Table_Abstract classes to get data from the database.
Each class has its own methods (getall, getXX, getYYY) etc…

My need was having all those method calls (around the code) automatically cached.
The first solution in my mind was a general wrapper (container) class that uses magic methods to call and cache methods of the inner class (subclass of Zend_db_Table_Abstract in this case).
The cache ID can be calculated by using class name +function name + arguments (md5+serialize).

public function __call($name, $arguments)
   $cacheId = get_class($this->wrappedObject) . $name
                . md5(serialize($arguments));
   // ...
   $callBack = array($this->wrappedObject, $name);
   //... cache logic...
   $ret = call_user_func_array($callBack, $arguments);
   // ...

I wanted the wrapper to work in a “invisible mode” in order to keep the IDE autocompletition for the model methods. So I’ve made a static method that instantiates the wrapper on the object passed by reference.

public static function createOn(&$wrappedObject, $lifetime = null)
    $wrappedObject = new self($wrappedObject);

Here it is an example of use

$modelCategories = new Application_Model_Categories();
CacheWrapper::createOn($modelCategories /*, 7200*/); //2nd param = lifetime
/* $modelCategories is now and instance of CacheWrapper 
 *  but the IDE still thinks is teh model */
$data = $modelCategories ->getAll(); //cached !
$data2 = $modelCategories ->getAll(1,2); //cached !

Cache and expiring time (value “randomized” by 10%) can be set using a static method (or taken from registry if existing).

EDIT 3/9/2013
source code moved to github:

3 thoughts on “Automatic caching of Zend_Db (or any object) calls

  1. Pingback: Optimising Zend Framework applications – part 1

  2. Too bad this doesn’t work with rowclass (Zend_Db_Table_Row_Abstract). It does cache, but when refreshing the page fatal errors will be given.

Comments are closed.