Tag: cakephp paginator

Speed up your pagination with a simple hack…

Before I go into the example in this little post, let me just say that this situation won’t be applicable to everyone…

But let’s consider the following:
We have a table with tens of thousands of records, that need to be paginated.

As you know, cake will execute two queries; first to get the count of total records, second to get the actual records.

The questions one might ask are:
“Would any user really go through 5 thousand pages to find what they are looking for?”
“If I bring the last 1,000 records wouldn’t that be enough for a vast majority of needs?”
“How many pages in Google do you go through, when searching for something, before you give up?”
“Is it not better to provide filters, or search tools to help your users narrow down the results to something manageable?”

If you’ve answered “Yes” to two or more questions, please consider the hack…

In your model, which needs to be paginated, do the following:

public function paginateCount($conditions = null,
                                 $recursive = 0,
                                 $extra = array()) {
   return 1000;
}

Yep, we are overriding paginateCount() and simply returning 1,000 because we know that this will be the maximum amount of records that our paginator needs to know about.
Depending on how complex the underlying query is (for example you might have JOIN’s or various conditions, which would usually need to be taken into the account in your typical count query), the above hack can dramatically increase the performance of your pagination.

Paginate associated model's data in CakePHP

This is a pretty simple tip, but I’ve noticed some beginners are having a problem with this scenario.

We are in the Users Controller and need to paginate all Comments for a given User (i.e. User.id = 5), well and probably display the User info while we are at it…
For this example we keep in mind that User hasMany Comment and Comment belongsTo User.

First, we prepare our controller to handle Comment pagination:

class UsersController extends AppController
{
    var $name = 'Users';

    var $paginate = array('Comment'=>array('limit'=>5));
}

Yep, even though we are in the Users Controller, we will be paginating the Comment model. (Obviously you can add other options, but we’ll just add a simple ‘limit’ for this example).

So what’s left to do?
Tell our paginate() method that we’ll be paginating the Comment model and pass appropriate User.id in the array of conditions:

[source language="php"]
function index() {
$this->set(‘comments’, $this->paginate($this->User->Comment, array(‘User.id’=>5)));
}
[/source]

Remember, that because Comment belongsTo User, cake will build a JOIN and pass the correct condition to retrieve all of the relevant comments for this User.

… and for a little extra bonus let’s throw in a simple view:

<?php echo $paginator->numbers(); ?>

<?php foreach($comments as $comment): ?>

<div>
    <?php echo $comment['Comment']['comment']; ?>
</div>

<?php endforeach; ?>

Displaying sort direction in paginated data

Just a little tip on styling your table with paginated data…

Wouldn’t it be nice to show to the user what column and direction is currently used for sorting of your data? Here’s how you can do that with a little CSS and some Paginator methods.

First, we need to find out in our view which column we use to sort and in what direction (ASC or DESC) the sorting goes:

$sortDir = $paginator->sortDir();
$sortKey = $paginator->sortKey();

Now that we know the two values, we can easily style the table header:

<th <?php echo ($sortKey == 'ID') ? 'class="'.$sortDir.'"' : ''; ?>>

In the example above, if our sorting field happens to be “ID” we assign a class=”asc” (for ascending) or class=”desc” (for descending), else no class is assigned.
This code uses a short-hand if/else condition, which is sometimes frowned upon, but I feel in this case it provides for a cleaner looking code.