Feed on

Based on feedback (and the long time between updates), I’m releasing an updated version of the PHP pagination class.


  • No more SQL errors if using the class on a query with no results (although I fail to see the point of using it on an empty query anyway, but the bug is fixed)
  • When selecting ‘ALL’ only one page is displayed, and if you are using the display_items_per_page drop-down menu, ‘ALL’ is now selected as well.
  • If a page less than page one, or greater than the total number of pages is requested, no results are displayed and the appropriate prevous/next links are disabled
  • The items per page array that populates the display_items_per_page drop-down menu is now an option that can be configured when instantiating the class. Previously this was hard-coded to the class.
  • The $high option has been removed from the class (it was never used).

Note that if you receive a PHP notice about undefined indexes that you should turn down your error reporting. This notice may be displayed when loading the page for the first time when no $_GET variables are present. The class accounts for this, however PHP throws a notice about it.


I’ve also added license info at the head of the class (CC Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)).


67 Responses to “PHP Pagination Class Updated – Version 2”

  1. Nathan says:


    I tried using v.1 and then v.2 of this pagination class and for some reason I can’t get the $pages->limit to work.

    I used
    $pages = new Paginator;
    $pages->items_per_page = 21;
    $pages->mid_range = 5;
    run query “select * from table $pages->limit”
    run query “select count(*) from table” for total items
    $pages->items_total = $totalitems;

    For some reason the $pages->limit never get initialized. I even tried echo out $pages->limit without the query and it stills show nothing. Do you have any idea what could be happening? Thanks.

    • admin says:

      I’d need to have access to your code. I dropped the new versions in the same old examples here and there were no issues.

      • Nathan says:

        Thanks for the reply. I figured out the problem.
        $pages->paginate() has to be called before I can use $pages->limit, unlike the other properties that were set.

      • I too am having this problem with the $pages->paginate(); having to be called first, Doing what Nathan said worked but It means that the word “All” is output twice, onces prior to the database call and one after including the pagination items.

        Im not sure if this is a bug or not.


      • Jay says:

        I’m having the same issue. The script works fine, but it’s not displaying any links to navigate through the results. All I get is an “All” button that correctly displays all results when clicked. If I manually enter ‘?page=3′ or whatever in my URL it works as expected. I’m just not getting any of the required HTML generated except for the “All” button.

  2. David says:

    Hi, Any reasons why the the pagination only shows a link to page 1 and a link showing all the pages? I have 20 items and limited the results to 2 items per page.

    • admin says:

      Is it doing that for you here on the demo?

      • SumJar says:

        I believe I’m seeing something similar to what Michael cited (referring to our own machines, not the online demo): I see ’1′ and ‘All’ (followed by the default 25 City records). Clicking ‘All’ does display all records, but I don’t see any pagination.

      • SumJar says:

        (David, not Michael!)

  3. Rajesh Shrestha says:

    How to make multiple pagination in single page? if have any idea please share with me… :)

  4. Adrian Somesan says:

    Hi, great example, one little change

    function display_jump_menu() {
    for ($i = 1; $i num_pages; $i++) {
    $option .= ($i == $this->current_page) ? "$i\n" : "$i\n";
    return "Page:items_per_page$this->querystring';return false\">$option\n";

    would produce a warning so just change the function like this:

    function display_jump_menu() {
    $option = '';
    for ($i = 1; $i num_pages; $i++) {
    $option .= ($i == $this->current_page) ? "$i\n" : "$i\n";
    return "Page:items_per_page$this->querystring';return false\">$option\n";

  5. Wade says:

    so my problem is this:

    $pages->items_total = XXXXXXXXXXXX;
    $pages->mid_range = 25;
    $pages->items_per_page = 50;
    $search = new search($_GET, $pages->limit);

    I won’t know the total number until my search obj is instantiated. I can’t do the search till I got a limit. I’m stuck in a catch 22.

    Any ideas?

    • admin says:

      Try reading the instructions carefully.

      • Wade says:

        I thought I had. My full code, with nothing left to assumptions (using version 2 of the class):

        //Step 1
        require( $_SERVER['DOCUMENT_ROOT'] . "/classes/paginator.class.php");
        //Step 3
        $pages = new Paginator();
        //Step 4
        $pages->items_total = XXXXXXXXXXXX;
        //Step 5
        $pages->mid_range = 25;
        $pages->items_per_page = 50;
        //Step 6
        //Step 8
        $search = new search($_GET, $pages->limit);

        The problem is, my query has WHERE clauses in it… and is dynamic. When I instantiate my search object, I have it doing two queries inside, one with the limit and one without to populate $this->numrows and $this->results. Should I consider reworking it slightly to perhaps instantiate two searches, one with and one without the limit and forget about the $this->numrows property?

  6. Michael says:

    Whenever I do a search, then click on the next page, it always goes back to the original listing.
    Example … I have 524 images I’m showing. Then, I do a search on say, photographer, which comes up with 175 images. It shows the right amount the first time (175), but when I click on the NEXT page, it always goes back to 524 images, instead of keeping the 175 I searched on?

    Search on “Barry” under photographer for an example.

  7. Shane says:

    Hi Great pagination class.
    I have 1 problem My site works through a template so my page links are in the format of /?index.php?page=gallery your pagination class works perfect as a standalone page but when I load it through my template in an include (“includes/gallery.php”); the page loads fine and the pagination links are all there but when I click a link on the pagination I get a not found 404 error.


    my gallery link = http://domain/index.php?page=gallery

    on the pagination links they are ilke this http://domain/index.php?page=2&ipp=15

    any help would be great thanks

    • admin says:

      I’d need to see your actual site/code to help.

      • Shane says:

        Hi below is the code of my index page which loads the other pages as includes and below that is the gallery page include. All works fine when access the gallery when it is not an include but when you use the gallery as the include it loads the page fine and displays all the links but the links do not work any help to solve this problem would be great.
        index page:

        Gallery include page:

        items_total = $num_rows[0];
        $pages->mid_range = 9;

        echo “”;
        echo “”.$pages->display_jump_menu().$pages->display_items_per_page().”";
        echo “”;
        echo “”;
        echo $pages->display_pages();
        echo “”;

        $query = “SELECT photoName, photoID FROM photos WHERE active = 1 order by photoID desc $pages->limit”;
        $result = mysql_query($query);

        echo “”;
        echo “”;
        while($row = mysql_fetch_array($result))

        echo “”;
        echo ““;

        echo “”;
        echo “”;

        echo “”;
        echo $pages->display_pages();
        echo “”;
        echo “Page $pages->current_page of $pages->num_pages”;
        echo “”;

  8. Shane says:

    This is the index page it did not get posted before i guess it was because i had the body tags in it.

  9. Shane says:

    I’ll try again. index page

    include (“includes/header.php”);

    case “home”:
    include (“includes/home.php”);
    case “contact”:
    include (“includes/contact.php”);
    case “gallery”:
    include (“includes/gallery.php”);
    include (“includes/404.html”);

    include (“includes/footer.php”);

  10. Emil says:

    Can you provide some Demos of usage?

  11. Emil says:

    Can you provide some demos?

  12. Emil says:

    I mean in zip file to check how to use this php class. In examples section of site the script is running. I need It’s code.

  13. Pablo Carrau says:

    I can’t seem to get the paging working correctly when dealing with random recordsets ( ORDER BY RAND() ). When you go to the second page, the query gets resorted and you end up seeing records that originally appeared on page 1 also appear on page 2 and so on. It works perfectly for queries by any other sort order, but random does not.

    Any advice on how to correct this would be greatly appreciated!

    • admin says:

      Random ordering won’t work because every time you change pages, the query gets executed and re-randomizes the results.

      • Pablo Carrau says:

        Thanks for the quick response.

        There’s no way to store the query in memory to continue traversing through it in page chunks?

      • admin says:

        No, that would be more of a JavaScript solution where you randomize your entire recordset, pass it to the user, and then paginate it on the client side. One of the advantages of this class is its speed, which it gets by limiting the size of the data requested. Randomizing it would effectively kill that, unless you randomized your recordset once and then stored it in another table to query from.

      • Pablo Carrau says:

        Nevermind…ended up using a seeded RAND(#) call instead and holding the value in a session variable. That way I can hold the random recordset during that session and renew on next. All works great that way :)

  14. Sandro says:

    Great! thanks. that’s what i was looking for since some time.
    It works so far but if i go through the pages one by one the url will add many of the same requests into it.
    thats the outcome. Not sure why this will happen.
    Any hint please ? Thanks

    • Michael says:

      Has to be your code. I have some pages up to 60 something, and it doesn’t do that on my site.

    • P. Silva says:

      First of all thanks admin for posting the code.
      Secondly, even though it’s almost been a year since your comment but I thought I’d post this anyway for someone that might be coming across this page from this point forward and has encountered the same issue you describe in the post.

      It seems like the cause for that behaviour (repeating the parameters in the query string) is related to this snippet of code in the paginate() method

      $args = explode("&",$_SERVER['QUERY_STRING']);
      foreach($args as $arg)
      $keyval = explode("=",$arg);
      if (($keyval[0] != "page") && ($keyval[0] != "ipp"))
      $this->querystring .= "&" . $arg;
      foreach($_POST as $key=>$val)
      if (($key != "page") && ($key != "ipp"))
      $this->querystring .= "&$key=$val";

      This is supposedly going to append any “key=value” pairs you might have in the query string other than “page” and “ipp”. If you comment these lines it will work like it should.

      Besides that, although it does filter the results based on what my option of the “Items per page” control is, the pagination links and the calculation used to populate the select control with each individual page number doesn’t seem to be working, it just displays “1 All” (regarding the display_pages() function) and “1″ in the select populated by the display_jump_menu() function.

  15. Michael says:

    Wish list …
    Images for next-previous-All.
    Option to remove ‘ALL’ if list hits certain amount – 500,1,000. (:

  16. Newb says:

    good stuff!
    can ask something?
    how can i implement this one in search..paginating the search result, thanks.

  17. Derek says:

    Really good work. I like it. Just one question though: for the drop down list and SELECT DISTINCT from…, how would I be able to also add an “ALL” (all records from table) option to the list?

  18. Alvaro says:


    I am having a strange issue witht the links of the pages.
    I get the result set well trimmed by Limit, and the page numbers.1,2,3 etc. However, all of the numbers are active. That is, the first page should have the number 1 unclickcable, however you can click on it. But, if you click on any number, then it is a “hasta la vista baby”. The whole line of link numbers disappear from sight. But, just now I found something interesting: if I reload the page, by F5 or up there in the circle arrow, I get a Firefox alert window telling me that in order to load the page it needs to send the query again. I click ok and I get then the next result set, page 2, I reload again and I get page 3.

    I have a Form submitting to itself and 3 select lists that provide the WHERE parameters for the sql query. Does this issue have anything to do with being a Form that submits to itself?
    Why would the whole row of Link numbers disappear if you click on any number?

    thank you

  19. Alvaro says:


    I am beginning to suspect, the mistery of the link numbers that disappear must have something to do with the fact that being a Self submitting form there is a flag that says: If the variables have been set, process the form. If they haven’t, just display it. If I click on the link numbers, looks like the variables are unset, and thus, only the form stays. I don’t know. I am baffled.

  20. Yogesh says:

    Thanks for such a brief and nice tutorial. Worked flawlessly. But I am wondering how I can generate the random result rather than in ascending or descending order with your pagination result.

  21. WindowsLover says:

    i’ve tried the new versione (2).. ERRORS:
    Notice: Undefined index: ipp in C:\wamp\www\Paginator_1\paginator.class.2.php on line 34
    Notice: Undefined index: ipp in C:\wamp\www\Paginator_1\paginator.class.2.php on line 106
    My code:
    $query = “SELECT * FROM news”;
    $result = mysql_query($query) or die(mysql_error());
    $num_rows = mysql_fetch_row($result);
    $pages->items_total = $num_rows;
    $pages = new Paginator;
    $pages->items_total = 10;
    $pages->mid_range = 5;
    echo $pages->display_pages();

    Thank You in advance :)

    • Yogesh says:

      Use @$_GET['ipp'] == ‘All’ instead of $_GET['ipp'] == ‘All’.
      In the version2 script you may also get an error for undefined variable $option. For that use $option = ”; inside display_jump_menu() function.

      Have fun!

  22. timoline says:

    I slightly changed the code so it will work with bootstrap twitter

  23. inap says:

    i faced the Pagination problems like
    1. Not included First, Next, Previous, Last links
    2. When included the searching the search parameter goes to in url
    3. Sorting is not for each column
    if you have a time please explain how to solve it?

  24. inpa says:

    Pagination class is fine. But following is included or i face following problems.

    1. Not included First, Next, Previous, Last links
    2. When included the searching the search parameter goes to in url, but for security it is very danger.
    3. Sorting for each column


  1. [...] (Oct 25, 2011): Version 2 now available for download. See here for more info. Note that the examples on this page still use an older version of the [...]

  2. [...] PHPÚltimamente ando revisando mis posts antiguos y en esta ocasión quería mostrarles una clase de paginación echa en PHP que es más fácil y prolija de usar que el código de Paginación PHP que publique hace tiempo. [...]

  3. [...] 1.9.0) Infinite Scrolling (JQuery Plugin) MySQL World Database (Importing can take some time!) Pagination Class (v2!) (Default Styles for Pagination [...]

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>