Cacheing each query individually

So lately I have been delving into the caching capabilities of CakePHP. Most, if not all of its capabilities work wonderfully; although I personally can't get into $cacheAction (within the controllers). The $cacheAction property only works for static and non-user generated pages, in other terms, any content that changes depending on a logged in user wont work correctly with $cacheAction (unless you want thousands and thousands of cache files). So I stopped using $cacheAction all together in my latest application, and instead built a method that caches individual queries, instead of the whole page. All the modifications have been applied to the models find() method. To use this, place the following code within your app/app_model.php.

/**
 * Wrapper find to cache sql queries
 * @param array $conditions
 * @param array $fields
 * @param string $order
 * @param string $recursive
 * @return array
 */
function find($conditions = null, $fields = array(), $order = null, $recursive = null) {
	if (Configure::read('Cache.disable') === false && Configure::read('Cache.check') === true && isset($fields['cache']) && $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];
			}
		}

		// Set cache settings
		Cache::config('sql_cache', array(
			'prefix' 	=> strtolower($this->name) .'-',
			'duration'	=> $expires
		));
		
		// Load from cache
		$results = Cache::read($key, 'sql_cache');
		
		if (!is_array($results)) {
			$results = parent::find($conditions, $fields, $order, $recursive);
			Cache::write($key, $results, 'sql_cache');
		}
		
		return $results;
	}
	
	// Not cacheing
	return parent::find($conditions, $fields, $order, $recursive);
}

In the next step, you would create a folder called sql within your tmp/cache/ and chmod the permissions to 777. Once you have created the folder, open up your app/config/core.php file and place the following code at the bottom (near the default cache settings).

Cache::config('sql_cache', array(
    'engine'		=> 'File',
    'path'		=> CACHE .'sql'. DS,
    'serialize'	=> true,
));

By default, caching will not work on your applications queries, you would need to set an additional "cache" option within your find(). Each SQL cache should have its own unique identifier so that it does not conflict with other queries. Also by default, queries will be cached for one hour and will be saved as a serialized array. The following examples explain how the cache option works.

// Cache query to /tmp/cache/sql/model-test_sql_query
$results = $this->Model->find('all', array(
	'cache' => 'test_sql_query'
));

// Cache query to /tmp/cache/sql/model-another_query that expires in 24 hours
$results = $this->Model->find('all', array(
	'cache' => array('another_query', '+24 hours')
));

What if I have a query that's used multiple times but each has its own limit (custom method), but uses the same cache slug? Simply give the cache slug a dynamic name like so:

// Cache query to /tmp/cache/sql/model-dynamic_query-15 
$results = $this->Model->find('all', array(
	'limit' => $limit, // 20, 30, etc
	'cache' => 'dynamic_query-'. $limit
));

I personally have found an increase in load times up to 150-200% faster using this method. This should only be applied to queries that are used on landing pages, and queries that do not change according to which user is logged in. Have fun.