Pagination with PHP

The other day, I was looking for a decent tutorial on creating pagination using PHP. I did a couple Google searches, but the results did not fit my criteria. I was looking for a caterpillar pagination where there is a head, a tail, and a middle section that moves along as you click through the pages.

Previously, the site I was working on had used a previous/next deal where the user would just keep clicking next to get further through the records. But, this type of navigation takes too long to get to the end and is not very search engine friendly.

I began by writing up use cases to give an overview of what the user would see. The use cases became the conditional in the pagination function.

Prior to loading the pagination function, I retrieved the cleaned page number from the parameter value in the URL and the total number of pages from the database. I passed these two values into the function.

function page_navigation($current_page, $total_pages) {
    var $html = "";
    var $previous_page;
    var $next_page;
    var $difference = $total_pages - $current_page;
    var $low_range = $current_page - 2;
    var $high_range = $current_page + 3;

Use case #1: The number of records pulled from the database fills less than 10 pages. When this happens, I rather just list every page for the user to see; the number is dependent on the width of your page and your style preference.

Visual Example: 1 2 3 4 5 6 7 8 9 10

    if ($total_pages <= 10) {
        for ($i=1; $i<=$total_pages; $i++) {
            $html .= ''.$i.' ';
        }
    }

Use case #2: The number of records pulled fills more than 10 pages but the user is currently viewing a page closer to the end. Choosing the amount of pages to list at the head or tail of the listing is also a preference. The difference is the total number of pages subtracted by the current page. I chose a difference of 4 pages; visually, it looks like 5. A nice round number.

Visual example: 1 … 16 17 18 19 20

    if ($total_pages > 10 && $difference < 4) {
        $html .= '1 ... ';
        for ($i=($total_pages-4); $i<=$total_pages; $i++) {
            $html .= ''.$i.' ';
        }
    }

Use case #3: The number of records pulled fills more than 10 pages but the user is currently viewing a page closer to the beginning.

Visual example: 1 2 3 4 5 … 20

    if ($total_pages > 10) {
        if ($current_page < 6) {
            for ($i=1; $i<7; $i++) {
                $html .= ''.$i.' ';
            }
            $html .= '... ';
            $html .= ''.$total_pages.' ';
        }
    }

Use case #4: The number of records pulled fills more than 10 pages but the user is viewing a page that is not close enough to the beginning or the end to trigger the previous two test cases. In this case, you will need to choose how many pages from the current page you wish to display. I chose two from each side so it would show 5 in the middle to match the beginning and the end. So, subtracting 2 from the current page gives the low range and adding 3 to the current page gives the high range. 3 is added for the high range because the current page is included in the high range section.

Visual example: 1 … 8 9 10 11 12 … 20

    if ($total_pages > 10) {
        if ($current_page > 6) {
            $html = '1 ... ';
            for ($i=$low_range; $i<$high_range; $i++) {
                $html .= ''.$i.' ';
            }
            $html .= '... '.$total_pages.' ';
        }
    }

The final part, I added a previous and next link to either side of the page navigation for users who need a bigger link to click.

Visual example: << prev 1 ... 8 9 10 11 12 … 20 next >>

    if ($current_page == 1) {
        $previous_page = ' << prev';
    } else {
        $previous_page = ' << prev';
    }
    if ($current_page == $total_pages) {
        $next_page = 'next >>';
    } else {
        $next_page = 'next >> ';
    }
    $html = $previous_page . $html . $next_page;

All the code ends up in the $html variable. You may print this out to the screen or return the value as I did in the complete code below.

function page_navigation($current_page, $total_pages) {
    var $html;
    var $previous_page;
    var $next_page;
    var $difference = $total_pages - $current_page;
    var $low_range = $current_page - 3;
    var $high_range = $current_page + 4;

    if ($total_pages <= 10) {
        for ($i=1; $i<=$total_pages; $i++) {
            $html .= ''.$i.' ';
        }
    } else if ($total_pages > 10 && $difference < 5) {
        $html .= '1 ... ';
        for ($i=($total_pages-5); $i<=$total_pages; $i++) {
            $html .= ''.$i.' ';
        }
    } else if ($total_pages > 10) {
        if ($current_page < 6) {
            for ($i=1; $i<7; $i++) {
                $html .= ''.$i.' ';
            }
            $html .= '... ';
            $html .= ''.$total_pages.' ';
        } else {
            $html = '1 ... ';
            for ($i=$low_range; $i<$high_range; $i++) {
                $html .= ''.$i.' ';
            }
            $html .= '... '.$total_pages.' ';
        }
    }
    if ($current_page == 1) {
        $previous_page = ' << prev';
    } else {
        $previous_page = ' << prev';
    }
    if ($current_page == $total_pages) {
        $next_page = 'next >>';
    } else {
        $next_page = 'next >> ';
    }
    $html = $previous_page . $html . $next_page;

    return $html;
}

The function is actually much smaller then what is seen above. Some of those lines can be condensed into one line and a few variables removed. I had to format the function in this manner for it to fit into the blog layout.

There is also a cosmetic feature that can be added to this function. If you want to make the current page number more prominent, you can drop a conditional statement into each of the for loops and compare the index value to the current page. If the two matches, then you can bold the link or add a style class.

3 thoughts on “Pagination with PHP

  1. Thanks for your article 🙂

    I made a few changes so that the function can be universal and used on multiple different pages. There was also some minor fixes to get the first page to show up as a link (1, 2, etc). other than that it’s a great function. Thanks again!

  2. Oh, I see the problem. I used the “&” for adding the page parameter to the URL when it should have been a “?”. It should be all better now.

Leave a Reply

Your email address will not be published. Required fields are marked *