A sample text widget

Etiam pulvinar consectetur dolor sed malesuada. Ut convallis euismod dolor nec pretium. Nunc ut tristique massa.

Nam sodales mi vitae dolor ullamcorper et vulputate enim accumsan. Morbi orci magna, tincidunt vitae molestie nec, molestie at mi. Nulla nulla lorem, suscipit in posuere in, interdum non magna.

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();
});

2 comments to Using PHP Closures to get cached object with one call

  • Yeah

    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.

  • Yeah

    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

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>