Caching Propel object in Symfony

This article has moved to this location.


Symfony offers us a very flexible and powerfull caching system. We can cache an action, partial, slot or cache the result of a function call. But how if want to cache the Propel objects?. Say you want to cache the list of customers. When the user add, update or delete on the customers data, the customers cache is deleted. In this article, i’ll share my idea on how to cache the propel objects using sfFunctionCache as the base class.
sfFunctionCache is an excellence class, but it’s has a limitation. We never know the generated cache name. In order to know the generated cache name, we have to do the same way as sfFunctionCache did.

md5(serialize($callable).serialize($arguments));

and it’s will be more complex if we include many arguments. Beside that, we have to know exactly the arguments we’ve supplied to the function. So, how if we want to give the descriptive name to the generated cache name?.
Here is what i’ve done. Extends the sfFunctionCache and override the computeCacheKey and call functions. If you don’t provide the key parameter, this class will behave as sfFunctionCache.

class myObjectCache extends sfFunctionCache
{
   protected $key = null;
   public function call($callable, $arguments = array(), $key = null)
   {
      $this->key = $key;
      return parent::call($callable, $arguments);
   }
	
   public function computeCacheKey($callable, $arguments = array())
   {
       return (null !== $this->key) ? $this->key : parent::computeCacheKey($callable, $arguments);
   }

  public function remove($key)
  {
      return $this->cache->remove($key);
  }
}

Below is an usage example of myObjectCache class :

//it's will generate the file cache with the name customers_list.cache
$cache = new myObjectCache(new sfFileCache(array('cache_dir' => sfConfig::get('sf_cache_dir').'/objects')));
$customers = $cache->call(array('CustomerPeer', 'doSelectOrderedByName'), array(new Criteria()), 'customers_list');

If the function doSelectOrderedByName is called in several places, we can move it to the class model

public static function doSelectOrderedByName(Criteria $c = null)
{
   $c = (null === $c) ? new Criteria() : clone $c;
   $c->addAscendingOrderByColumn(self::NAME);
   return self::doSelect($c);
}

public static function doSelectOrderedByNameFromCache(Criteria $c = null)
{
   $cache = new myObjectCache(new sfFileCache(array('cache_dir' => sfConfig::get('sf_cache_dir').'/objects')));
   return $cache->call(array('CustomerPeer', 'doSelectOrderedByName'), array($c), 'customers_list');
}

And the example above become :

//it's will generate the cache with the name customers_list.cache
$customers = CustomerPeer::doSelectOrderedByNameFromCache();

To delete the generated cache, override save and delete functions of your model.

//Customer.class.php
public function save(PropelPDO $con = null)
{
   $retval = parent::save($con);
   if ($retval > 0)
   {
      $this->removeCustomerCache();
   }
   return $retval;
}

public function delete(PropelPDO $con = null)
{
    parent::delete($con);
    $this->removeCustomerCache();
}

protected function removeCustomerCache()
{
   $cache = new myObjectCache(new sfFileCache(array('cache_dir' => sfConfig::get('sf_cache_dir').'/objects')));
   $cache->remove('customers_list');
}

Hope it useful…

Advertisements

2 responses to “Caching Propel object in Symfony

  1. Kuba February 5, 2010 at 7:14 pm

    Looks simple. Thanks for the tip!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: