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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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:
1 2 3 4 5 6 | Cache::config('paginate_cache', array( 'engine' => 'File', 'path' => CACHE .'sql'. DS, 'serialize' => true, 'duration' => '+1 hour', )); |




1 trackbacks/pingbacks
Comments About Pagination Caching With CakePHP
// 3 comments so far.
trent // February 25th 2010
Thanks Bigtime!!! I’ve been searching a solution to cache paginated queries! This seems to work great!
anagram // March 10th 2010
it doesn’t work on my app … it’s broken when a pagination use a containable
any workaround for this issue? Thx
VoiDeT // March 10th 2010
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.
You can follow any responses to this entry via its RSS comments feed. You may also leave a trackback by clicking this link.