info:cake:pagination

Source: http://bakery.cakephp.org/articles/view/pagination

fichier tar modifié par mes soins - version française

Pagination
Tutorials Oct 9, 2006
Details

    * Version: 1.1.x
    * Views: 120179
    * Comments (102) 

Rating

    * 4.84 by 25 Users

 

    * Log in to add rating

Tags

    * page 

    * Log in to add tags

More...

    * Page 2: Additional info

By Andy Dawson (AD7six)
If you have more than a few results it is useful, if not vital, to provide a means of presenting the results a few at a time.
This tutorial will demonstrate how easy it is to present your data using pagination.
If part of your application includes displaying lots of results, it's a good idea to give the user the possibility to view the results in digestable chunks and possibly to be able to sort the presented data. This tutorial will explain how, after copying a few files into your application, you can achieve this in very few lines of code.
You need almost no knowledge of cake to be able to make use of this tutorial :).

If you already have a table in mind that you want to add pagination to, read on; otherwise run through http://manual.cakephp.org/appendix/blog_tutorial to have some code to play with.

Setting Up
All of the files necessary are available here in the bakery.

Save this file http://bakery.cakephp.org/articles/view/67 as /app/controllers/components/pagination.php

Save this file http://bakery.cakephp.org/articles/view/68 as /app/views/helpers/pagination.php

Save this file http://bakery.cakephp.org/articles/view/69 as /app/views/elements/pagination.thtml

Create/modify the Controller
The only change necessary to use pagination is to include the component, the helper and call the component method "init" before the relavent find.
Controller Class:
Download code <?php 
class PostsController extends AppController
{
    var $name = 'Posts'; // for PHP4 installs
    var $components = array ('Pagination'); // Added
    var $helpers = array('Pagination'); // Added

    function index() {    
        $criteria=NULL;
        list($order,$limit,$page) = $this->Pagination->init($criteria); // Added
        $data = $this->Post->findAll($criteria, NULL, $order, $limit, $page); // Extra parameters added
        
        $this->set('data',$data);
    }
}
?>
Create/modify the View
To make use of pagination, include the element, and optionally modify your table headers to allow changing the sort order of results:
View Template:
Download code
<h1>Paginated Posts Index</h1>
<table>
<?php
$pagination->setPaging($paging); // Initialize the pagination variables
$th = array (
            $pagination->sortBy('id'),
            $pagination->sortBy('title'),
            $pagination->sortBy('created')
); // Generate the pagination sort links
echo $html->tableHeaders($th); // Create the table headers with sort links if desired

foreach ($data as $output)
{
    $tr = array (
        $output['Post']['id'],
        $html->link($output['Post']['title'], "/Posts/View/{$output['Post']['id']}"),
        $output['Post']['created']
        );
    echo $html->tableCells($tr,array('class'=>'altRow'),array('class'=>'evenRow'));
}
?>
</table>
<? echo $this->renderElement('pagination'); // Render the pagination element ?>

Adding Ajax updates
If you include the RequestHandler component, the AJAX helper in your controller and the prototype js file is loaded in your view - you get your updates by ajax. Yes, it's that simple. The div that will be updated by default is the "content" div, you can change this by specifying in the component (either directly, or at run time) which div to update. And yes, you can disable this automatic behaviour if required.
How to add Prototype
So how do you add the prototype library..? Well...
Modify your layout

The Prototype JavaScript library is availble at http://prototype.conio.net/ put prototype.js in /app/webroot/js/
Add the JavaScript code inside the tag

PHP Snippet:
Download code <?php 
if(isset($javascript)):
    echo $javascript->link('prototype.js');
endif;          
?>

Page 2: Additional info
Comments 65
CakePHP Team Comments Author Comments
 
Comment
1 GET string creation
Hello,

great code and a nice tutorial, thanks for sharing it!

I'm not sure if you can consider this a bug, but I was getting html validation errors because of "&" in the get string (like in: "/users/index?sortBy=email&page=2".

I've changed the line 550 in the helper
$getString = implode ("&", $getString);

to this:
$getString = implode ("&amp;", $getString);

and it was ok.

regards, danielz
Posted Oct 11, 2006 by DanielZ
 
Comment
2 modelClass attribute
Hi, thanks for this great component. I had some difficulties when requesting data from another model than the controller's default.
I have worked around it by setting the attribute $this->Pagination->modelClass to the Model name I wanted to use. I think that it should be then a public attribute, or maybe rethink the component to accept different Model names for Default sortBy condition and for counting the elements returned by the criteria would be a nice enhancement.
Posted Oct 12, 2006 by Jose Lorenzo Rodriguez
 
Comment
3 modelClass attribute
"I had some difficulties when requesting data from another model than the controller's default.
I have worked around it by setting the attribute $this->Pagination->modelClass to the Model name I wanted to use. I think that it should be then a public attribute, or maybe rethink the component to accept different Model names for Default sortBy condition and for counting the elements returned by the criteria would be a nice enhancement."
This already is a public attribute. Just pass the key 'sortByClass' with your Modelname as the value in the third options array for init(). For example:

$this->Pagination->init(null,null, array('sortByClass'=>'Foo','sortBy'=>'bar'));

Posted Oct 13, 2006 by Jean-Claude Siegrist
 
Question
4 Unclear error
But what if the controller is for more than one models and it's not called as model itself. In my case I have one admincontroller and when I try to initalize pagination I get this error.

Notice: Undefined property: AdminController::$Admin in C:\apache2triad\htdocs\cake_plugin\app\controllers\components\pagination.php on line 212 Fatal error: Call to a member function findCount() on a non-object in C:\apache2triad\htdocs\cake_plugin\app\controllers\components\pagination.php on line 212
Posted Oct 16, 2006 by Peco Danajlovski
 
Comment
5 Reply
Hi all,

"I have worked around it by setting the attribute $this->Pagination->modelClass ..." Following up on what Jean-Claude Siegrist has said, that's not really necessary. For any field you can override what is in the component by passing info in the 3rd paramter. For this example $this->Pagination->init(null,null,array('modelClass'=>'otherModel'));

Regarding the admin error, and bypassing commenting on the use of admin routes, this can also be solved in the same way. Although I am not sure how that error occurs as by default the component uses the controller modelClass (have you set your controller $uses var to null?).
Posted Oct 16, 2006 by Andy Dawson
 
Question
6 Keeping the search criteria from page to page
Using the pagination component, you have initial control over the criteria you give to it (from a search page typically), as in:

list($order, $limit, $page) = $this->Pagination->init($criteria);

However, when you render the pagination element, you seem to have no control anymore on the criteria. With the following rendering, shifting to another page (or asking for a different page size) makes you loose your filtering:

$this->renderElement("pagination");

Is there a technique to make the criteria available consistently through the page and page siez links ?

Posted Oct 23, 2006 by Iharizaka Rahaingoson
 
Comment
7 Great Component
Thanks man I really like the way this component works. Simple and easy.
Posted Oct 23, 2006 by Carlos Mauricio Samour
 
Question
8 Sorting by associated attributes
Great component, thanks!

Quick question - if you have a table based on a particular model and you want to display sortable columns where sortable them take data from another (associated) model, how is this done? In the tutorial above for example, how would you add a sortable column that shows the post's author name?

I've tried switching the model via the 3rd parameter of $pagination->sortBy but that didn't seem to work instead throwing 'SQL Error in model: Unknown column'. Any suggestions?

Posted Oct 26, 2006 by Andrew Jessup
 
Comment
9 Reply
Hi all,

I'd recommend the link "Page 2: Additional info" if the first page doesn't satisfy your thirst for knowledge :).

Iharizaka Rahaingoson:
There are 2 main ways of handling searches
1) Process the form and redirect the user to a page with the constraint in the url
2) 'Pull' the search form info with each pagination link (requires Ajax).

I would recommend the first, and I've spoken about it on the google group a few times; there are demos of both from the links of "Page 2: Additional info".

Andrew Jessup:
Also on "Page 2: Additional info" you'll see a description of each of the parameters. To change the model used in the sort you would specify sortByClass. Be aware that the pagination component simply feeds info back for you to use in your subsequent findAll - if it's not possible to sort the results by the class that you specify (if the association for the class you specify is not hasOne or belongsTo the primary search won't contain the class), you'll get error messages and/or no results.

Anyway, HTH
Posted Oct 26, 2006 by Andy Dawson
 
Comment
10 Pagination rocks
Thanks Andy for devoting your time to this, pagination is awesome ; ).
Posted Oct 27, 2006 by Felix Geisendoerfer
 
Question
11 sortBy not having any effect
To my understanding sortBy is used to set the default sort order, if I am not wrong it will set the ORDER BY value for the generated sql statement.

I have tried bothe the approch


$this->Pagination->direction = 'ASC';
$this->Pagination->sortBy = 'created';
list($order,$limit,$page) = $this->Pagination->init($criteria);

~~~AND~~~

list($order,$limit,$page) = $this->Pagination->init($criteria,null,array('sortBy' => 'created', 'direction' => 'DESC'));

In both the cases when I am changing the value of direction its working properly but the sortBy stuff is not working. Even I change the value of

/**
* Specify DEFAULT sort column.
*
* @var string
* @access public
*/
var $sortBy = 'id';

to

var $sortBy = 'created';

the generated SQL is still showing

...ORDER BY `Event`.`id`...

Am I doing something wrong. I have read both the articles several time .. Am I missing something? Your help is highly appreciated and I am thankful to you for this component. If you can please help me to solve the issue , that will be very nice.

* Please forgive me for my bad English :) cheers

suman
Posted Oct 31, 2006 by Suman Paul
 
Question
12 Changing limit
Hi, I'm new to all this so I'm having some issues. I did this tutorial with a table that has thousands of records. It all works, but with only 5 results per page I get far too many pages. I went into the controller and changed the line
$data = $this->Post->findAll($criteria, NULL, $order, $limit, $page);
to
$data = $this->Post->findAll($criteria, NULL, $order, 100, $page);

It changed the results page to 100 records but at the bottom is still says "Results: 1-5 of 2373". Where can I change that?
Posted Nov 3, 2006 by Ro
 
Comment
13 set resultsPerPage array
Hi Ro,

I guess you have to set resultsPerPage in the controller
so this :

$this->Pagination->resultsPerPage = array(100,200,500);
$this->Pagination->show = 100;
list($order,$limit,$page) = this->Pagination->init($criteria);

I think that will solve the issue.

cheers
Posted Nov 3, 2006 by Suman Paul
 
Comment
14 Reply
"To my understanding sortBy is used to set the default sort order" 100% correct, but there was a missing if statement in a previous version of the component which caused the sort field to always be overwritten with the primary key field. Note I say "was" that was corrected on 2006-09-25. If you take the code from the bakery that problem is solved.

[quote}$data = $this->Post->findAll($criteria, NULL, $order, 100, $page); That will certainlly work, but of course the pagination code won't know that you are overriding the values it's giving you :).
If you want to fix completely the number of results, such that the user can't change them you could do:
PHP Snippet:
<?php 
$settings = array (
    'resultsPerPage' => array(100),
    'privateParams' = array("show");
);
list($order,$limit,$page) = $this->Pagination->init(NULL,NULL,$settings);
?> The resultsPerPage parameter set's the possibilities that you can choose from, and the privateParams parameter means you can't change it from the web. (Note that: In this example it's not necessary to specify the privateParms, because if you try to show a number of results that are not in the resultsPerPage array - the default value is used.)

If you wanted simply to change the default number of results that are displayed when you first load the page, you could do:
PHP Snippet:
<?php 
$settings = array (
    'show' => 100
);
list($order,$limit,$page) = $this->Pagination->init(NULL,NULL,$settings);
?> Or any other permutation you can think of :). Again, I'd recommend page 2 of this article for the description of parameters and links to the examples which you can download.
Posted Nov 4, 2006 by Andy Dawson 
  • info/cake/pagination.txt
  • Dernière modification : 2018/07/18 12:05
  • de 176.9.50.244