CakePHP & Caching Until a Future Post

CakePHP & Caching Until a Future Post

We had implemented a caching system for all find, pagination and pagination count methods with CakePHP. You can find a post on this here. The cache was expiring after every hour, however we failed to realise something. Our CMS system that we built allows posts to show up on the website at a later date, that is, you could set a publish date. Since the cache was only for an hour, or cleared when a new post was added/edited, then there would be a lag time for these new posts to show up. Instead we decided set the expiry date/time of the cached objects to their next future update, for example:

if (!empty($this->_schema['published_date'])) {
	$next = $this->find('first', array('conditions' => array($this->name.'.published_date > NOW()'), 'order' => array($this->name.'.published_date'), 'recursive' => -1));
		if (!empty($next)) {
		$expires = $next[$this->name]['published_date'];
		// Set cache settings
		Cache::config('sql_cache', array(
			'duration'	=> $expires
		));
	}
}

So what this snippet does is tests whether or not the current model being used has a field that would allow it to be posted into the future. This is done in $this->_schema['published_date']. From there you can override the cache settings expiry time to that of the post’s publish date. In reality you could have an infinite expiry on cache, if there are no future posts to post, as your system should also clear cache on add/editing of posts.

This blog post wasn’t exactly clear, as i wrote it on the spur of the moment, but you get the idea. If you want the full context of the find caching on generic models you can check it out:

function find ($conditions = null, $fields = array(), $order = null, $recursive = null) {
	if (Configure::read('Cache.disable') === false && Configure::read('Cache.check') === true && is_array($fields) && array_key_exists('cache', $fields) && $fields['cache'] !== false) {
		$key = $fields['cache'];
		$expires = '+1 hour';

		if (is_array($fields['cache'])) {
			$key = $fields['cache'][0];

			if (isset($fields['cache'][1])) {
				$expires = $fields['cache'][1];
			}
		}
		Cache::config('sql_cache', array(
			'prefix' 	=> strtolower($this->name) .'-',
		));

		// Load from cache
		$results = Cache::read($key, 'sql_cache');


		if (empty($results)) {
			if (!empty($this->_schema['published_date'])) {
				$next = $this->find('first', array('conditions' => array($this->name.'.published_date > NOW()'), 'order' => array($this->name.'.published_date'), 'recursive' => -1));
				if (!empty($next)) {
					$expires = $next[$this->name]['published_date'];
				}
			}
			
			// Set cache settings
			Cache::config('sql_cache', array(
				'duration'	=> $expires
			));
			
			$results = parent::find($conditions, $fields, $order, $recursive);
			Cache::write($key, $results, 'sql_cache');
		}
		return $results;
	}

	// Not cacheing
	return parent::find($conditions, $fields, $order, $recursive);
}

Please note the original idea to override the find method was from Miles Johnson over at http://www.milesj.me/blog/read/34/Cacheing-Each-Query-Individually……genius

Posted by voidet

Categorised under CakePHP
Bookmark the permalink or leave a trackback.

2 Trackbacks

  1. [...] rest is here: CakePHP & Caching Until a Future Post • Jotlab If you enjoyed this article please consider sharing [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

or
Links:nike air max pas chernike air max pas chernike tn pas cherray ban pas chernike air max pas chernike tn pas cherray ban pas cherray ban pas cherray ban pas cher