CakePHP Part 6 - Pagination!

Skill

CakePHP Part 6 - Pagination!

Posted in:

So far in our Cake tutorials, we have learned the basics of CakePHP, and used some pretty time saving and neat features. Thus far, most of these features we have implemented have been easy fixes to small issues, that save at most a few hundred of code. Today, we will be using a really neat view/controller combo that will make creating a paginated view as easy as.....well, cake!

Pagination is something that any decent site has in it somewhere. The whole idea is to give the user pages of information to look through, instead of just listing all the data at once. Not only does this cut down on page load times, but it is also a great way to view and organize the information as well. And like always, Cake makes this task just as easy as a few lines of code.

Paginating the Controller

There are a lot of ways to accomplish a nicely paginated layout, some more efficient than others. The way Cake handles this task is by limiting the SQL queries, in effect only giving up the chunk of records it needs for a specific page. As usual, however, it is mostly automated and all we have to do is tell it that we want the data paginated. But, in this special case, it requires us to work both in the controller and the view.

The first part of this process is telling Cake to paginate all of our data retrieving calls, at least for a specific controller. To do this we are, curiously enough, going to add a variable to our controller class. The $paginate variable will tell Cake the basic parameters for paginating any data requests we want paginated. Right now, we are going to use the most basic form. All you need to do is add the variable in the list of class variables, I added mine under the helpers list:

var $name     = "Products";
var $helpers  = array(
              'Html',
              'Session'
              );
var $paginate = array(
              'limit' => 4,
              'order' => array(
                'Product.product_id' => 'asc'
                )
              );                

So, this simple array will tell Cake to limit our pages to 4 records, and sort them by the Product IDs. Now that we have the parameters all ready to go, we need to change the data retrieving call in our index() action so it will paginate our data. To do this we simply change our find() call to a paginate call, like this:

function index()
{
  $data = $this->paginate('Product');
  $this->set('data', $data);
}

You can see how easy it is to convert your find('all') call to a paginate() call. The only real difference is the outcome, and the fact that you have to use the $paginate class variable as your options array, rather than putting the options in the actual paginate() call.

The Results are Paginated!

Yeah, that's right, they are totally Paginated!

At this point, you should be able to load up the site and get your 4 records to show up. There is an immediate issue here though. You don't have any way to get to the next pages. This being the case, we have to move on to the view to accomplish this.

The View Controls

The view side of this whole ordeal you've probably guessed by now. We need some navigation controls to get us from page to page. Luckily, and thankfully, Cake has a companion pagination helper, for just that. You have probably also already guessed the first step, adding the helper to our controller list. So, our final controller variables will look something like so:

var $name     = "Products";
var $helpers  = array(
              'Html',
              'Session',
              'Paginator'
              );
var $paginate = array(
              'limit' => 4,
              'order' => array(
                'Product.product_id' => 'asc'
                )
              );                

Notice the addition of the Paginator helper. This will get us the navigation we need, as well as having a pretty awesome name. Names aside, there is really only one addition we need to make to our view.

We will be putting our navigation inside of a div, so it is easier to style later on. Besides the div, all we will have is a single call to the Paginator helper. The end result will be something along the lines of:

<?php
echo $html->css('default');
 
echo $html->link(
    'Add New Product',
    array(
      'controller' => 'Products',
      'action'     => 'add',
    ),
    array(
     
    ),
    null
);
?>


<table>

<?php

echo $html->tableHeaders(
    array(
      'Product ID',
      'Product',
      'Description',
      'Price'
    )
  );

foreach($data as $product)
{
  echo $html->tableCells(
      array(
        array(
          $product['Product']['product_id'],
          $product['Product']['product_name'],
          $product['Product']['product_desc'],
          $product['Product']['product_price']
        )
      )
    );
}

?>

</table>

<?php

echo $html->div(
  null,
  $paginator->prev(
    '<< Previous',
    array(
      'class' => 'PrevPg'
    ),
    null,
    array(
      'class' => 'PrevPg DisabledPgLk'
    )
  ).
  $paginator->numbers().
  $paginator->next(
    'Next >>',
    array(
      'class' => 'NextPg'
    ),
    null,
    array(
      'class' => 'NextPg DisabledPgLk'
    )
  ),
  array(
    'style' => 'width: 100%;'
  )
);  

?>

Paginated With Navigation

Now with shiny new navigation!

At the very bottom of our main page, we have our page navigation. The Paginator helper makes the "Previous" and "Next" links, but also keeps track of the current page and whatnot. This makes it quite easy to make the links we need. It can also make page number links, which we did using the $paginator->numbers() call. In the Previous and Next links, we also have specified CSS classes for both enabled and disabled stats. This will allow us to easily style them. Other than that, everything is pretty much "magic".

A Quick Styling

The basic navigation is good enough, but that is about it. It is squished together, so it doesn't look that great. Good thing we added some CSS classes already, huh? All we have to do now is add some new style definitions in our default.css file. Just as a reminder, this file can be found in cake_root/app/webroot/css/. Once you open it up, just add the following:

.PrevPg
{
  margin-right: 10px;
}

.NextPg
{
  margin-left: 10px;
}

.DisabledPgLk
{
  width: 100px;
  display: inline;
}

Final Outcome

Our Styled Navigation.

This will give our navigation a nice, neat spacing. Once you have that added, you have completed your pagination. Although in its simplest form, you can still appreciate how easy Cake makes the whole process. From start to finish, it probably takes 5 minutes at the most to add pagination to your application. how cool is that? Just don't forget, when you need help, all you have to do is Switch On The Code.

*This tutorial was created using CakePHP v1.2.1.80004, and Documentation Version 1.2

Adnan
01/25/2010 - 05:57

What about sorting by derived fields like AVG, SUM ? CakePHP does not support sort by derived field. But you can achieve it a simple easy tweak. Here is the details in my blog post: http://abcoder.com/php/cakephp/cakephp-advanced-pagination-sort-by-derived-field/

Hope you'd like my idea.

Thanks
Adnan

reply

Israel Morales
04/13/2011 - 15:27

Thanks very much this tutorial is more helpfull than the one on the cakephp.org site!!

reply

Amir Nasiruddin Sayani
10/18/2011 - 00:29

Great Article....

Worked....

reply

Akarsh
10/19/2011 - 16:40

This made my day!Amazing Post!

reply

boby
10/26/2011 - 15:13

very good, thanks

reply

Anonymous
11/09/2011 - 08:53

Hello

Im getting this error message when trying to paginate.

Warning (512): Controller::paginate() - can't find model equipos in controller EquiposController [CORE\cake\libs\controller\controller.php, line 1104]

I've included this var in the controller

var $paginate = array('limit' => 25);

This is the function in the controller (line with arrow)

function index1()
{
$this->set('equipos',$this->Equipo->find('all'));
---->> $data = $this->paginate('equipos');
$this->set('equipos', $data);
}

Anyone has a idea of whats happening????

thx in advance......

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.