Abbreviated Results Pagination in PHP

December 18, 2008

In my PHP and MySQL for Dynamic Web Sites: Visual QuickStart Guide book I demonstrate how to paginate query results over multiple pages like you’d see on a search results page. Here’s an image from that example:

Pagination Example from the Book
The code in that example creates links for every page. If you have hundreds or more returned results, this isn’t practical. The solution is to rewrite the code that creates the links so that it only shows a few links at a time.

In the book’s example, a simple FOR loop goes through the number of pages and creates links for each one, except for the current page:

for ($i = 1; $i < = $pages; $i++) {
    if ($i != $current_page) {
        echo '<a href="this_page.php?s=' . (($display * ($i - 1)));
        echo '&p=' . $pages . '">' . $i . '</a>';
    } else {
        echo $i . ' ';
} // End of FOR loop.

To create a partial set of links, you need to change the parameters of this FOR loop so that it only goes from X to Y, where X is a point before the current page and Y is a point after. Start with a variable representing the number of links to show before and after this page:

$z = 5; // How many links to show before or after current page.

Now you could determine the starting point by just subtracting $z from the current page but that would cause problems if the current page is not greater than the value of $z (in other words, if this is the first page, you wouldn’t want to show links to pages 0, -1, -2, -3, and -4). The same goes for the links after the current page: you shouldn’t eclipse the total number of pages that exist. Using the ternary operator, I can set the value of the first link as the current page minus $z, if that value is greater than 0, or just 1. I set the value of the last link as the current page plus $z, if that value is less than or equal to the number of pages, or just the number of pages.

$before = ( ($current_page - $z) > 0 ) ? ($current_page - $z) : 1; 

$after = ( ($current_page + $z) <= $pages ) ? ($current_page + $z) : $pages;

Once those two values are calculated, the FOR loop can be rewritten to use them:

for ($i = $before; $i <= $after; $i++) {...

And that’s all there is to it! Here’s how this looks in practice:

The links after a couple of pages in.

The links after a couple of pages in.

Links in the middle of the results.

Links in the middle of the results.

Links on the last page.

Links on the last page.

I hope that helps and let me know if you have any questions about any of this code.