Custom caching in your Drupal module


Recently I needed to implement caching for a custom Drupal module. I needed my module to cache exactly every 30 minutes on the hour and half-hour.

After doing my homework, I found the necessary Drupal functions in cache_get() and cache_set().

Additionally, I found a good warning in this Civic Actions blog post (Drupal Gotchya: Cache_get() Returns Expired Items) about Drupal relying on cron to determine whether a cache has expired.

The best way to handle caching the way you want is to write some custom wrapper functions. This will give you the ability to deal with edge cases as you need. Here are my custom cache_get and cache_set functions.

/* * Wrapper for cache getting * @param: key - an arbitrary name given to the cached data * @return: the cached data */ function mymodule_get_cache($key = 'asheville') { // get cache $cache = cache_get('mymodule:'.$key); // if no cache or expired, reset it if (!$cache || (time() > $cache->expire)) { // reset cache using our cache_set wrapper function $data = mymodule_set_cache($key); // for testing purposes, let's output some information for the admin $admin_message = "The cache was just rebuilt"; } else { $data = $cache->data; // I'm a big fan of letting the admin know what's going on $admin_message = "This cache expires on ".date("l, M d Y - g:i.s A ",$cache->expire); } // show admin the cache time global $user; if ($user->uid == 1) { $data .= "
"; } return $data; } /* * Wrapper for cache setting * My needs are that the cached page updates it self every 30 minutes. This is reflected below. * @param: key - an arbitrary name given to the cached data * @return: the data that was cached */ function mymodule_set_cache($key = 'asheville') { // get the data however you want, here I have a custom theme function returning the data $data = theme('mymodule', mymodule_get_data()); // get expire time $sql = "SELECT expire FROM {cache} WHERE `cid` = '%s' LIMIT 1"; $last_expire = db_result(db_query($sql, 'mymodule:'.$key)); // in case of trouble if ($last_expire == 0) { $now = time(); // previous 30 minutes; $last_expire = $now - ($now % (60*30)); } // add 30 mins to the expire time $expire = strtotime('+30 minutes', $last_expire); // adjust for next day if (date('g:iA',$last_expire) == '11:30PM') { $expire += (60*60*24); } // set the new cache cache_set('mymodule:'.$key, $data, 'cache', $expire); // add a notice to the watchdog for reference watchdog('mymodule_cache', 'MyModule Cache: New cache was set and expires at %date', array('%date' => date("l, M d Y - g:i.s A", $expire)), WATCHDOG_NOTICE); return $data; }