Pagination

Summary

The main goal of these classes is to make it easy to paginate data. However, this is not monolithic or one size fits all solution. The pagination module provides a layered range of solutions in which developers can pick and choose to tailor the classes to their needs.

Specific Goals

Basics

The base object in this pagination system is a Value Object that holds the values for the list and does the necessary calculations. This class can be used alone, but if you do, you are required to initialize it manually.

$pager = new A_Pagination_Core($datasource);
$pager->setCurrentPage(intval($_GET['mypagevar']));
$pager->setNumItems(intval($_GET['mycountvar'])); 

This component also provides a class that extends the Core class and initializes itself from the HTTP Request so you don't have to initialize it manually. This class adds a process() method that will initialize the object for you:

$pager = new A_Pagination_Request($datasource);
$pager->process(); 

This Core object does the necessary calculation and will return page numbers for the current first, last, next and previous pages, plus a range of page numbers around the current page. These are intended to provide the basic functionality on which to build classes to render paginated output.

This class takes a Datasource object passed to the constructor. These Datasources comply to a simple Adapter interface. This component will provide Adapters for arrays, PDO, MySQL, etc. A getItems() method is provided to retrieve the records for the currently displayed page.

The basic methods in its interface are:

class A_Pagination_Core {
     function __construct($datasource)
     function isPage($number)
     function getPage($number)
     function getCurrentPage()
     function getFirstPage()
     function getLastPage()
     function getPageRange()
     function getNumItems()
     function getItems()
} 

Layered Design

This component is not monolithic. There are several levels of classes that use a Core object and provide support for rendering output. The lowest level of output support uses page numbers from a Core object and builds URLs. Using this class you can have complete control of your template:

$url = new A_Pagination_Helper_Url($pager);
$out .= '<a href="' . $url->previous() . '">Prev</a> ";
$out .= '<a href="' . $url->next('Next') . '">Next</a> ";

The next level of output support uses page numbers from a Core object and builds complete links ( tags). You an pass the name of a CSS class to this object to control link style:

$link = new A_Pagination_Helper_Link($pager);
$out .= $link->previous('Prev', 'mylinkclass');
$out .= $link->next('Next', 'mylinkclass');

Use Case Example

Here is an example of combining the classes to do a basic paginated list with links:

// create a data object that has the interface needed by the Pager object
$datasource = new Datasource();
 
// create a request processor to set pager from GET parameters
$pager = new A_Pagination_Request($datasource);
 
// initialize using values from $_GET
$pager->process();
 
// create a "standard" view object to create pagination links
include 'A/Pagination/View/Standard.php';
$view = new A_Pagination_View_Standard($pager);
 
// display the data
echo '<table border="1">';
foreach ($pager->getItems() as $row) {
    echo '<tr>';
    echo '<td>' . $row['id'] . '</td><td>' . $row['name'] . '</td>';
    echo '</tr>';
}
echo '</table>';
 
// display the pagination links
echo $view->render(); 

Additional Features

DataGrid

For the most automated use case, we will be providing a DataGrid that takes care of all HTML once the core classes have been finalized.

Levels of Functionality

We are trying to build a layered solution that allows people to pick the level they want to deal with. That is the reason why this component is build with a bunch of small, single purpose classes (besides that being a good practice ). So the levels, from lowest to highest, are:

Page Numbers

$pager = new A_Pagination_Core($datasource);
echo $pager->getNextPage();

Output: 8

URLs

$pager = new A_Pagination_Core($datasource);
$url = new A_Pagination_Helper_Url($pager);
echo $url->next();

Output: http://mysite.com/mypage.php?page=8

Links

$pager = new A_Pagination_Core($datasource);
$link = new A_Pagination_Helper_Link($pager);
echo $link->next();

Output: 8 (Note this is a link () to the URL above

Standard View Helper

$pager = new A_Pagination_Core($datasource);
$view = new A_Pagination_View_Standard($pager);
echo $view->render();

Output: First Prev 5 6 7 8 9 Next Last

All-in-one

$view = new A_Pagination_Standalone($datasource);
echo $view->render();

Output: First Prev 5 6 7 8 9 Next Last

We have also discussed possibly implementing different View Helpers to allow you to do pagination links like Google, phpBB, Flikr, etc. (e.g. A_Pagination_View_Google). All of the core functionality to build those is in the lower layers.

It is also our intention to provide a simple DataGrid. (And we may do a Ajax-ified, edit-in-place version as well)

Data Grid

$pager = new A_Pagination_Request($datasource);
$view = new A_Pagination_View_Datagrid($pager);
echo $view->render();

Output (obviously it would be in columns in a table):

ID Title Category
11. Foo One edit
12. Bar Two edit
13. Baz Two edit
14. Faz One edit
15. Boo Two edit
First Prev 5 6 7 8 9 Next Last

Note that there are options to control how/when Prev/Next are displayed. Note also that ORDER BY link generation and datasource sorting functionality is also build-in to the core classes. I don't know that was mentioned above.)