Zebra_Pagination, a generic pagination class written in PHP

Get the latest updates on this PHP library via RSS

A generic pagination script that automatically generates navigation links as well as next/previous page links, given the total number of records and the number of records to be shown per page. Useful for breaking large sets of data into smaller chunks, reducing network traffic and, at the same time, improving readability, aesthetics and usability.

Adheres to pagination best practices (provides large clickable areas, doesn’t use underlines, the selected page is clearly highlighted, page links are spaced out, provides “previous page” and “next page” links, provides “first page” and “last page” links – as outlined in an article by Faruk Ates from 2007, which can now be found here, can generate links both in natural as well as in reverse order, can be easily, localized, supports different positions for next/previous page buttons, supports page propagation via GET or via URL rewriting, is SEO-friendly, and the appearance is easily customizable through CSS.

Please note that this is a *generic* pagination script, meaning that it does not display any records and it does not have any dependencies on database connections or SQL queries, making it very flexible! It is up to the developer to fetch the actual data and display it based on the information returned by this pagination script. The advantage is that it can be used to paginate over records coming from any source like arrays or databases.

Zebra_Pagination‘s code is heavily commented and generates no warnings/errors/notices when PHP’s error reporting level is set to E_ALL.

Top

Features review

  • it is a generic library: can be used to paginate records both from an array or from a database
  • it automatically generates navigation links, given the total number of items and the number of items per page (examples of best practices are also included)
  • navigation links can be generated in natural or in reverse order
  • is SEO-friendly – it uses rel=”next” and rel=”prev” and solves the problem of duplicate content on the first page without navigation and the first page having the page number in the URL
  • appearance is easily customizable through CSS
  • code is heavily commented and generates no warnings/errors/notices when PHP’s error reporting level is set to E_ALL
  • has comprehensive documentation

Top

Requirements

PHP 5+

Top

Installation

Download the latest version, unpack it, and put it in a place accessible to your scripts.

Top

How to use

Make sure that in the <head> of your page you have

<link rel="stylesheet" href="path/to/Zebra_Pagination/public/css/zebra_pagination.css" type="text/css">

If you want to preserve hashes in the URL, also include the JavaScript file – simply including it will suffice;
(jQuery needs to also be loaded before loading this file)

<script type="text/javascript" src="path/to/Zebra_Pagination/public/javascript/zebra_pagination.js"></script>

Paginate data from an array:

<?php
// let's paginate data from an array...
$countries = array(
    // array of countries
);

// how many records should be displayed on a page?
$records_per_page = 10;

// include the pagination class
require 'path/to/Zebra_Pagination.php';

// instantiate the pagination object
$pagination = new Zebra_Pagination();

// the number of total records is the number of records in the array
$pagination->records(count($countries));

// records per page
$pagination->records_per_page($records_per_page);

// here's the magick: we need to display *only* the records for the current page
$countries = array_slice(
    $countries,
    (($pagination->get_page() - 1) * $records_per_page),
    $records_per_page
);

?>

<table>

    <tr><th>Country</th></tr>

    <?php foreach ($countries as $index => $country):?>

    <tr<?php echo $index % 2 ? ' class="even"' : '')?>>
        <td><?php echo $country?></td>
    </tr>

    <?php endforeach?>

</table>

<?php

// render the pagination links
$pagination->render();

?>

View output

 

Paginate data from MySQL:

<?php
// how many records should be displayed on a page?
$records_per_page = 10;

// include the pagination class
require 'path/to/Zebra_Pagination.php';

// instantiate the pagination object
$pagination = new Zebra_Pagination();

// the MySQL statement to fetch the rows
// note how we build the LIMIT
// also, note the "SQL_CALC_FOUND_ROWS"
// this is to get the number of rows that would've been returned if there was no LIMIT
// see http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
$MySQL = '
    SELECT
        SQL_CALC_FOUND_ROWS
        country
    FROM
        countries
    LIMIT
        ' . (($pagination->get_page() - 1) * $records_per_page) . ', ' . $records_per_page . '
';

// if query could not be executed
if (!($result = @mysql_query($MySQL))) {

    // stop execution and display error message
    die(mysql_error());

}

// fetch the total number of records in the table
$rows = mysql_fetch_assoc(mysql_query('SELECT FOUND_ROWS() AS rows'));

// pass the total number of records to the pagination class
$pagination->records($rows['rows']);

// records per page
$pagination->records_per_page($records_per_page);

?>

<table class="countries" border="1">

    <tr><th>Country</th></tr>

    <?php $index = 0?>

    <?php while ($row = mysql_fetch_assoc($result)):?>

    <tr<?php echo $index++ % 2 ? ' class="even"' : ''?>>
        <td><?php echo $row['country']?></td>
    </tr>

    <?php endwhile?>

</table>

<?php

// render the pagination links
$pagination->render();

?>

Paginate data from MySQL in reverse order:

<?php
// how many records should be displayed on a page?
$records_per_page = 10;

// include the pagination class
require 'path/to/Zebra_Pagination.php';

// instantiate the pagination object
$pagination = new Zebra_Pagination();

// show records in reverse order
$pagination->reverse(true);

// when showing records in reverse order, we need to know the total number 
// of records from the beginning
if (!($result = @mysql_query('SELECT COUNT(id) AS records FROM countries'))) 

    die (mysql_error());

// pass the total number of records to the pagination class
$pagination->records(array_pop(mysql_fetch_assoc($result)));

// records per page
$pagination->records_per_page($records_per_page);

// the MySQL statement to fetch the rows
// note the LIMIT - use it exactly like that!
// also note that we're ordering data descendingly - most important when we're 
// showing records in reverse order!
$MySQL = '
    SELECT
        country
    FROM
        countries
    ORDER BY
        country DESC
    LIMIT
        ' . (($pagination->get_pages() - $pagination->get_page()) * $records_per_page) . ', ' . $records_per_page . '
';

// if query could not be executed
if (!($result = @mysql_query($MySQL)))

    // stop execution and display error message
    die(mysql_error());

?>

<table class="countries" border="1">

    <tr><th>Country</th></tr>

    <?php $index = 0?>

    <?php while ($row = mysql_fetch_assoc($result)):?>

    <tr<?php echo $index++ % 2 ? ' class="even"' : ''?>>
        <td><?php echo $row['country']?></td>
    </tr>

    <?php endwhile?>

</table>

<?php

// render the pagination links
$pagination->render();

?>

View output

Top

Download

version 2.1.1
If you find this library to be useful to you, you can support the author by donating a small amount via PayPal:

Zebra_Pagination is distributed under the LGPL.

In plain English, this means that you have the right to view and to modify the source code of this software, but if you modify and distribute it, you are required to license your copy under a LGPL-compatible license, and to make the entire source code of your derivation available to anybody you distribute the software to.

You also have the right to use this software together with software that has different licensing terms (including, but not limited to, commercial and closed-source software), and distribute the combined software, as long as state that your software contains portions licensed under the LGPL license, and provide information about where the LGPL licensed software can be downloaded.

If you distribute copies of this software you may not change the copyright or license of this software.


You may also like:

Top

Documentation

Documentation Become a ninja.
Read the comprehensive documentation.

Top

Changelog

Click on a version to expand/collapse information.

version 2.1.1 (July 15, 2013)
  • fixed a bug where wrong class name was used in the JavaScript files;
  • project is now available on GitHub and as a package for Composer
version 2.1 (February 06, 2013)
  • fixed some bugs with having pagination links shown in reverse order; thanks to marcin for all the feedback;
  • position of next/previous links can now be changed so instead of being on the outside of the links to individual pages these can now be shown also either to the left or to the right; see the newly added navigation_position method;
version 2.0 (January 28, 2013)
  • dropped support for PHP4; the library now requires PHP5+;
  • fixed a bug where if parts of the URL had HTML entities, these would wrongly be encoded again by the library when generating the pagination links; thanks to Phil;
  • “next page” and “previous page” links will now show their associated labels by default (label were previously hidden from the library’s stylesheet file); labels can be changed/localized with the newly added labels method; also, the “next page” and “previous page” links are now always visible instead of just when there were more pages than the value of selectable pages;
  • pagination links can now be generated also in reverse order; use the newly added reverse method for that; thanks to marcin for suggesting;
  • everything is now centered by default;
  • changed the “next” and “previous” icons;
  • tweaked the CSS file;
version 1.4 (September 03, 2012)
  • in order to make the library more SEO friendly and to indicate the relationship between component URLs in a paginated series, rel=”prev” and rel=”next” were added to previous/next links; read more about pagination with rel=”next” and rel=”prev”; thanks to Igor;
  • corrections and additions to the documentation; thanks to Roberto Gomes
version 1.3 (May 03, 2012)
  • the URL specified through the “base_path” method can now contain query strings; previously query strings in this value got automatically removed; also, any query strings existing in the page’s URL were *always* preserved – now the “base_path” method accepts an additional argument to disable this behavior; thanks to Kesuma, Augusto Carvalho dos Santos, moregatest and to all the people reporting these things;
  • by also including a newly added JavaScript file, hashes in the URL can now also be preserved; the simple inclusion of the JavaScript file will do the trick; not including it will mean that hashes will not be preserved; thanks to Alan for requesting this;
version 1.2.2 (October 14, 2011)
  • fixed a bug where query strings got deleted if URLs were SEO friendly; thanks to theyouyou;
  • added a new method for setting whether the script should add a trailing slash to the URLs when generating SEO friendly URLs; read more on the subject on Official Google Webmaster Central Blog; thanks to theyouyou for suggesting.
version 1.2.1 (September 25, 2011)
  • fixed a bug that appeared in version 1.2 that would remove all query string parameters from the URL, except the page-related one; thanks to kumbing for reporting;
  • when method is “url”, the link to the first page does not include the “page” parameter anymore, in order to avoid duplicate content; previously this was true only for when method was “get”;
version 1.2 (September 18, 2011)
  • the link to the first page does not include the “page” parameter anymore, in order to avoid duplicate content; thanks to Sebi Popa for suggesting;
  • some optimizations were made in the code;
version 1.1c (May 05, 2011)
  • fixed a bug with the “next” link, when on first page; thanks to Jan for reporting.
version 1.1b (April 30, 2011)
  • fixed a bug where disabling the “next” and “previous” links, when on first or last page respectively, was not working properly; thanks to Javier for reporting.
version 1.1 (March 20, 2011)
  • fixed a bug where the “padding” method was not working (thanks to D. Koper for reporting);
  • fixed a bug where the “set_page” method was not working correctly (thanks to D. Koper for reporting);
  • when there is a single page available, the pagination links are not displayed anymore (thanks to Sebi P. for the suggestion);
  • default style was tweaked a bit;
version 1.0.1 (January 08, 2011)
  • entire code was audited and improved;
  • cleaner output;
  • more complete examples were added;
  • method names, method arguments and global properties were changed and therefore this version breaks compatibility with previous ones;
version 1.0 (June 04, 2009)
  • initial release;

Top

172 responses to “Zebra_Pagination, a generic pagination class written in PHP”

Follow the comments via RSS
  • Wilma, 2013-12-16, 17:15

    Your great script stopped working after my hosting company upgraded to PHP5.4

    Opening the webpage shows
    01 02 03 04 05 06 07 09 09 10 … 25 next
    But on page?9 it shows
    previous 1 2 3 4 5 6 7 8 9
    and the next button disappeared

    $records_per_page = 10;

    Reply
    • Stefan Gabos, 2014-02-07, 15:09

      I am unable to reproduce this on PHP 5.4.12. Maybe your query is wrong

  • Reke, 2013-12-17, 18:07

    At first i would thank you for the very good PHP Script, Stefan.
    It works very well.

    But i have now a problem with the “url” method.
    My startpage address looks like this:

    http://localhost/einhundertelf/website/site/

    with “url” method and the variable “seite” next pages must been look like this

    http://localhost/einhundertelf/website/site/seite2,
    http://localhost/einhundertelf/website/site/seite3 etc.

    on the startpage it works very well, but on another page the links look like this for Example:

    http://localhost/einhundertelf/website/site/seite3?seite=4

    I have an RewriteRule in my htacces:

    RewriteRule ^seite(.*)$ index.php?seite=$1 [L]

    Can you help me Please?

    Greets from Germany,

    Reke

    Reply
    • Stefan Gabos, 2013-12-17, 20:53

      that’s because you must set the method to “url”…

    • Reke, 2013-12-18, 13:26

      Hi,

      i have already done this. Today It works with all links.
      I don´t know, maybe the cache was´nt emptied.

  • Gunju, 2014-01-26, 22:38

    finally i configured in my localhost works perfect. thanks a lot. ;-)

    Reply
  • Guy, 2014-02-10, 13:35

    Great script, my page numbers have a leading 0 in front of them. How can I remove them please ?

    Reply
    • Stefan Gabos, 2014-02-10, 13:41
      $pagination->padding(false);
  • Karan, 2014-02-27, 15:06

    The pagination displays, when i click on number 2 or 3 to get to next page, it displays the same page

    Reply
  • edo, 2014-03-15, 15:43

    Hi, Stefan thank you for this class, it’s really helpful, i already the Docs, but i cant find how to add additional variable to the pagination outpot, for example i want the output to be like this = http://localhost/index.php?page=1&type=product, how can i accomplish this

    thank you in advance

    Reply
    • Stefan Gabos, 2014-03-17, 09:48

      it’s actually there in the documentation

      $pagination->base_url('http://localhost/index.php?type=product', true);
  • manisankar, 2014-09-08, 07:38

    is it possible implement filter option in this pagination?i tried it.but first page correct data,if i go to the Other page,full records automatically fetched.how to solve the issue

    Reply
  • Rick, 2014-09-15, 01:28

    How can I use a variable returned via form in the where clause?

    Reply
  • Josh, 2014-09-15, 14:26

    Hey Stefan, thanks for the great plugin! I’m trying to get this working on a custom PHP file within WordPress (don’t ask why :)) I’ve hit a brick wall though. WordPress automatically redirects any /page2/, /page3/ etc. to /page/2/, /page/3/ etc. This messes up the pagination (basically it doesn’t show records beyond 1st page). I tried changing the variable_name(), method(), base_url() etc. for no avail. Is there something I can do to get this working? Thanks in advance!

    Reply
  • Larry, 2014-09-16, 23:34

    Stephan… Excellent plugin, very simple to set up and use, however I’m having an issue with a website that I am currently trying to use it on. I have .htaccess rule set to display URLs with .html extension like this:
    RewriteRule ^([^/]*)/([^/]*)/page-([^/]*)\.html$ /community.php?city=$1&community=$2&p=$3 [L]

    If I visit the 1st page link, which looks like this: /naples/olde-naples.html, the plugin wants to add the next page url after the .html like this: /naples/olde-naples.html/page-3, when I want it to display it like this: /naples/olde-naples/page-3.html.

    I’ve tried changing settings, and even tried to add some logic in with the code to avoid this but to no avail. Any ideas on how this can be accomplished?

    Thanks!

    Reply
  • Sam Fourie, 2014-10-16, 18:01

    Hi there very easy script. just one question.. not knowing much about PHP and JS how and where would I change it so that the page numbers appear below or above the prev and next links so that i can use this in a responsive bootstrap page

    Thank you
    Sam

    Reply

Leave a Reply

Your email address will not be published
You can use <strong>, <em>, <a>, <img>, <code>
Characters are not case-sensitive