Pagination
Dropping a large result-set into small ones, you got from a table is a common task for web-developers. Krystal has a dedicated component for this task. Alright, let's start from the beginning, read on...
Style adapters
First of all, we need to configure a style adapter. It has only one option, which is style
. That option defines an optional style adapter for service's getPageNumbers()
method. Let's take a look at available options, before we start configuring the component.
Digg
If you have a large amount of page numbers, this style adapter is a great choice. For example, if you have 40 pages, a resulting rendered array with pages would look like as following:
1 2 3 ... 40
1 ... 3 4 5 6 7 ... 40
This similar to StackOverFlow's style
Slide
If you like how Yahoo styles their pagination block, then this adapter is what you want. The rendered array might look like so:
3 5 6 7 8
If the page number is 5
Configuring the service
Open configuration file, which is typically stored in config/app.php
. In components
section, you should see paginator
sub-section with only one option style
. See there? Good. This options accepts either Digg
or Slide
options for the style adapter respectively. If you omit the option, then no style adapter is used.
Usage
You're done with configuration. Now it's time to see how pagination can be used. This section assumes that you have a basic knowledge of mappers.
Fetching a result-set from a table
First of all, create module called Book
for this.. Suppose we have a table called books
and there are about 40 books. Since all table interaction are usually wrapped in data mappers, let's create a class for this table and name it BookMapper
, like this:
<?php
namespace Book\Storage\MySQL;
use Krystal\Db\Sql\AbstractMapper;
class BookMapper extends AbstractMapper
{
public function fetchAllBooksByPage($page, $perPageCount)
{
return $this->db->select('*')
->from('books')
->paginate($page, $perPageCount)
->queryAll();
}
}
Pretty easy? Isn't it?
Also note that paginate()
method is not a part of Pagination component. It's a part of Database component that implements Smart-Pagination algorithm. When you call it passing $page
and $perPageCount
it will tweak pagination behind the scenes for you.
Defining routes and controller
To make pagination work, it somehow must be aware of page parameter. Typically this is done by providing a route parameter, like /books/page/3
. So, let's implement this right now. Open your configuration file, where you store all your routes and add new two routes:
// ....
'/books' => array(
'controller' => 'Book@indexAction'
),
'/books/page/(:var)' => array(
'controller' => 'Book@indexAction'
)
// ...
Done. We'd use two routes for the same action in Book
controller class. Now let's create Book
controller with indexAction
. For simplicity, we'd avoid a service and build BookMapper
right in the action.
class Book extends AbstractController
{
public function indexAction($page = 1)
{
// Grab the BookMapper first, before we start
$mapper = '/Book/Storage/MySQL/BookMapper';
$bookMapper = $this->mapperFactory->build($mapper);
// $bookMapper is ready to be used
// Now grab all books, this must be called first
$books = $bookMapper->fetchAllBooksByPage($page, 5);
// Now configure pagination URL
$paginator = $bookMapper->getPaginator();
$paginator->setUrl('/books/page/(:var)');
// Done
return $this->view->render('books', array(
'books' => $books,
'paginator' => $paginator
));
}
}
Since we extended AbstractMapper
we already have inherited getPaginator()
method that returns pagination service object. Also note, that pagination URL must equal to the route that has been attached to controller's action.
Yeah, that's how its used. Let's examine what we did, if it's still not clear. First, we created a mapper, then we fetched all result-set and configured pagination URL, so that when users click on your links then will be redirected to appropriate page number.
Finally, last thing we need to take a look at is a list of available methods that $paginator
service object has. So read on.
Available methods
Typically you would want to use these methods in view templates to build pagination block.
getFirstPage()
\Krystal\Paginate\Paginator::getFirstPage()
Returns first page number, which is always 1.
getLastPage()
\Krystal\Paginate\Paginator::getLastPage()
Returns last page number. If we have 40 pages, the last one is 39.
getSummary()
\Krystal\Paginate\Paginator::getSummary($separator = '-')
Returns summary string. This typically used for displaying how many records are show on current page, i.e (1-3).
isCurrentPage()
\Krystal\Paginate\Paginator::isCurrentPage($page)
Determines whether passed number is a current page. This method typically used in view templates inside foreach
to add some kind of class="active"
for elements.
hasPages()
\Krystal\Paginate\Paginator::hasPages()
Determines whether there's at least one page available. Returns boolean.
hasAdapter()
\Krystal\Paginate\Paginator::hasAdapter()
Determines whether style adapter was defined in configuration. Returns boolean.
getPageNumbers()
\Krystal\Paginate\Paginator::getPageNumbers()
Returns an array of page numbers. This method is aware of style adapter, so if you defined a one in configuration, it will break-down the resulting array accordingly.
hasNextPage()
\Krystal\Paginate\Paginator::hasNextPage()
Determines whether current page has a next one. For example, if you're on 39 page and want to know if there's 40'th page, you'd use this method to determine it.
hasPreviousPage()
\Krystal\Paginate\Paginator::hasPreviousPage()
Determines whether there's a previous page, which is opposite to hasNextPage()
you see above.
getNextPage()
\Krystal\Paginate\Paginator::getNextPage()
Returns next page number if any.
getPreviousPage()
\Krystal\Paginate\Paginator::getPreviousPage()
Returns previous page number if any.
getCurrentPage()
\Krystal\Paginate\Paginator::getCurrentPage()
Returns current page number.
getNextPageUrl()
\Krystal\Paginate\Paginator::getNextPageUrl()
Returns next page URL.
getPreviousPageUrl()
\Krystal\Paginate\Paginator::getPreviousPageUrl()
Returns previous page URL.
getItemsPerPage()
\Krystal\Paginate\Paginator::getItemsPerPage()
Returns per page count number.
getTotalAmount()
\Krystal\Paginate\Paginator::getTotalAmount()
Returns total amount of records.