Sponsor
Now Playing
- Alix Perez – I'm Free 2 hours ago
- Alix Perez – Intersections 2 hours ago
- Alix Perez – Forsaken 2 hours ago
- Glen E Ston – Ouroboros (Original Mix) 2 hours ago
- Black Sun Empire – Everything 3 hours ago
Pagination Caching With CakePHP
February 9, 2010,
1,058 views
A site i was working with was using pagination quite extensively with lots of records and associations. This was producing unnecessary high load on the database and wait times on the production site. Caching had to be done. Unlike normal returned data from finds etc. Paginated data can not be cached as easily, as the paginate method needs to be called to generate the pagination numbers etc. So what was done was to do a custom pagination query with cache built in. So in your app_model.php file add in:
function paginate ($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) {
$args = func_get_args();
$uniqueCacheId = '';
foreach ($args as $arg) {
$uniqueCacheId .= serialize($arg);
}
if (!empty($extra['contain'])) {
$contain = $extra['contain'];
}
$uniqueCacheId = md5($uniqueCacheId);
$pagination = Cache::read('pagination-'.$this->alias.'-'.$uniqueCacheId, 'paginate_cache');
if (empty($pagination)) {
$pagination = $this->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'group', 'contain'));
Cache::write('pagination-'.$this->alias.'-'.$uniqueCacheId, $pagination, 'paginate_cache');
}
return $pagination;
}
function paginateCount ($conditions = null, $recursive = 0, $extra = array()) {
$args = func_get_args();
$uniqueCacheId = '';
foreach ($args as $arg) {
$uniqueCacheId .= serialize($arg);
}
$uniqueCacheId = md5($uniqueCacheId);
if (!empty($extra['contain'])) {
$contain = $extra['contain'];
}
$paginationcount = Cache::read('paginationcount-'.$this->alias.'-'.$uniqueCacheId, 'paginate_cache');
if (empty($paginationcount)) {
$paginationcount = $this->find('count', compact('conditions', 'contain', 'recursive'));
Cache::write('paginationcount-'.$this->alias.'-'.$uniqueCacheId, $paginationcount, 'paginate_cache');
}
return $paginationcount;
}
This will then take over from any paginate calls and generate a cached version of the dataset for the paginated items and the pagination controls, unique to each page and query set. I am in the process of trying to convert this over to a behaviour, will post up if i get a chance to complete it.
Of course you need to specify the caching rule in core.php, something like:
Cache::config('paginate_cache', array(
'engine' => 'File',
'path' => CACHE .'sql'. DS,
'serialize' => true,
'duration' => '+1 hour',
));
12 Comments
Thanks Bigtime!!! I’ve been searching a solution to cache paginated queries! This seems to work great!
it doesn’t work on my app … it’s broken when a pagination use a containable
any workaround for this issue? Thx
What exactly is broken?
I’ve used this on my apps and the pagination caches fine with contains, as you can see it is included in the finds. What you might have to do is included the extra array into the unique cache id, but i’d be surprised if you’re getting conflicting caches.
Anagram please explain what is going on.
i m also have used this to cache the pagination (thanks for sollution
), but i am get a problem with $paginator (prev/next),
thanks a lot for the code.
just one question: how can I temporarily disable the pagination-caching?
I got some views in the backend where I need fresh data.
Hey Daniel,
I would simply use the extras parameter or add another parameter that would accept a cache disabled test, then i would just use that to turn the cache off or on in the method.
Let me know if you need help to achieve this and i can post a modified version.
Hi,
thanks for the answer. That’s exactly what I did yesterday and it works perfectly.
My problem was that I first tried to put the parameter in the paginate-call and not in the controllers paginate variable.
Hi,
thanks for the answer. That’s exactly what I did yesterday and it works perfectly.
My problem was that I first tried to put the parameter in the paginate-call and not in the controllers paginate variable.
To make sure the custom paginate function also works with Contain:
On line 13; remove ‘recursive’.
When using Containable, you most likely defined $recursive = -1; in your AppModel. The function compact on line 13 uses this variable, wich would mean, recursive is passed with the find function on line 13 and there fore, you explicitly ask for no recursion.
i m also have used this to cache the pagination (thanks for sollution
), but i am get a problem with $paginator (prev/next),
Great tutorial, just one question… How do I reset the cache using an afterSave method?
You can use Cache::delete(‘paginate_cache_unique_id’); in your afterSave() method to clear out the cache for the pagination. Just change the key to whatever you used to generate your pagination cache with. Or if you want to flush all cache for pagination then you can use the Cache::clear(expiration_check, config_name) method
2 Trackbacks
[...] Pagination Caching With CakePHP [...]
[...] 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 [...]