Using PHP Closures to get cached object with one call

Getting caching objects if a fairly frequent task when dealing with performative web applications.

Standard approach

if (cache object is valid)  {
return cached object
} else {
get fresh object (*)
save object into cache
return object
}

I don’t like that approach as there are a lots of LOC that wraps the only meaningful code (to get the fresh object).

Easier approach with PHP Closures (anonymous functions): one function call

$data= getWithCache(function(){
  //calculate $freshObject
  return $freshObject;
});
//use $data !!

Much easier, isn’t it ?

Implementation of the function (uses Zend_Cache)

/** Caches the return value of the passed function.
 * Zend_registry 'cache' must be defined. By phpntips.com
 *
 * @param Closure $f anonymous function called when cache is not valid
 * @param string $cacheID cache ID, reflection info are used if not specified
 * @return mixed cached Object
 */
function getWithCache(Closure $f, $cacheID = null)
{
    $cache = Zend_Registry::get('cache');
    if ($cacheID === null) {
        $cacheID = md5(serialize(Reflection::export(new ReflectionFunction($f), true)));
    }
    if ($cache->test($cacheID)) {
        return $cache->load($cacheID);
    } else {
        $ret = $f();
        $cache->save($ret, $cacheID);
        return $ret;

    }
}

A concrete example

$posts = getWithCache(function(){
    $zsd = new Zend_Service_Delicious('elvis...', '...');
    return $zsd->getAllPosts();
});
You can leave a response, or trackback from your own site.

2 Responses to “Using PHP Closures to get cached object with one call”

  1. Yeah says:

    I really like this idea but you need PHP 5.3. Another way is to use exceptions:

    function getResultCached() {
    try {
    return $this->readCache(“key”);
    } catch (CacheMissException $cme ) {
    $result = ..;
    return $this->writeCache($result,$cme);
    }
    }

    Now readCache throws a CacheMissException when the key is not found, and stores the cachekey in the exception so it can be reused by writeCache.

  2. Yeah says:

    Hmm, I don’t know how to properly paste code here, but this is wat the cache functions look like:

    protected function readCache($cache_key) {
    $cached = $this->cache->get($cache_key);
    if (isset($cached))
    return $cached;

    throw new CacheMissException($cache_key);
    }

    protected function writeCache($object,$cme) {
    $this->cache->set($cme->getKey(),$object);
    return $object;
    }

Leave a Reply