PHP Pagination Class Updated – Version 2

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

Changes

  • 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.

Examples

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

Download

70 thoughts on “PHP Pagination Class Updated – Version 2”

  1. Hi,

    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;
    $pages->paginate();

    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.

      1. 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.

      2. 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.

        Cheers
        Dan.

      3. 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. 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.

      1. 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.

  3. 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";
    }

  4. so my problem is this:

    $pages->items_total = XXXXXXXXXXXX;
    $pages->mid_range = 25;
    $pages->items_per_page = 50;
    $pages->paginate();
    $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?

      1. 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
        $pages->paginate();
        //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?

  5. 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.

  6. 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.

    Example

    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

      1. 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;
        $pages->paginate();

        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 “”;
        ?>

  7. I’ll try again. index page

    include (“includes/header.php”);

    $page=(isset($_GET['page']))?$_GET['page']:’home’;
    switch($page){
    case “home”:
    include (“includes/home.php”);
    break;
    case “contact”:
    include (“includes/contact.php”);
    break;
    case “gallery”:
    include (“includes/gallery.php”);
    break;
    default:
    include (“includes/404.html”);
    break;
    }

    include (“includes/footer.php”);

  8. 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!

      1. 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.

      2. 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 :)

  9. 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.
    /index.php?page=16&ipp=25&ipp=25&ipp=25&ipp=25&ipp=25&ipp=25&ipp=25
    thats the outcome. Not sure why this will happen.
    Any hint please ? Thanks

    1. 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


      if($_GET)
      {
      $args = explode("&",$_SERVER['QUERY_STRING']);
      foreach($args as $arg)
      {
      $keyval = explode("=",$arg);
      if (($keyval[0] != "page") && ($keyval[0] != "ipp"))
      {
      $this->querystring .= "&" . $arg;
      }
      }
      }
      if($_POST)
      {
      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.

    1. What would be the easiest way to eliminate the option for the user to be able to choose ‘ALL’ as part of the class?

      Thanks, this is a GREAT little piece of code!

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

  11. Hi,
    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?

  12. Hi,

    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

  13. Update.

    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.

  14. 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.

  15. 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;
    $pages->paginate();
    echo $pages->display_pages();

    Thank You in advance :)

    1. @WindowsLover:
      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!

Leave a Reply

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

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