In the years that I’ve been a web developer, I have written very few OOP PHP scripts. I just haven’t had the need to, and to be honest the whole OOP concept seemed like something I didn’t need to bother with. Why do I need to write a script in an object-oriented style and how will it help me? I had seen examples and read tutorials about OOP (some horribly bad and some really good) but never had any desire to try it myself until one day when I was working on a couple of different projects that both needed the same thing, pagination.
Pagination just means numbering pages. In the project that I was working on, I was retrieving large amounts of data from a MySQL database and realized that I would have to break the data up into pages for two main reasons, 1) there was so much data that it could hang the browser when it was loading and 2) from a user perspective (we still care about that right?) it was unruly to say the least. If I was returning 50,000 rows from a database query, I knew that I would need to slice that up into more manageable chunks. Now in the past, I had written basic pagination functions to handle this type of issue and sometimes copied and pasted functions from older scripts to cut down on development time, fixing and re-coding where necessary. But I realized that for this new project I could try to write a pagination class that I would be able to just plug into any script and have it do the pagination for me. I could write a pagination class that I could use for my projects and future projects, and learn OOP in the process. I love killing two birds with one stone.
Which brings me to our pagination class (paginator.class.php). Now I’m not claiming to be the first person to write a pagination class — far from it. But I do feel that this one is the most lightweight, feature-rich, and easy to use that I’ve seen. For an example of the pagination class in action, click here.
To download the pagination class, click here.
Update (Aug 4, 2009): Some of you have asked for more examples of the PHP pagination class I wrote, specifically the same examples I’m using here on the site. The database comes from MySQL’s free example databases available at http://dev.mysql.com/doc/#sampledb (my example uses the world database). The two examples I use here can be seen at http://www.catchmyfame.com/paginator/example.php and http://www.catchmyfame.com/paginator/example-form.php. You can download both PHP files in a zip file. You’ll need to setup the database yourself and fill in the example PHP files with your database info. Don’t forget to grab the sample database from MySQL.
In the example below, you can see the paginator used at the top and bottom of the database query.

In this example, you can see the mid range property which creates a range of pages around the current page and the use of … to distinguish the break between contiguous pages

In this example you can see the optional items per page drop down menu

In this example you can see the optional page jump menu

In this example we see how the previous and next buttons are sensitive to what the current page is.

This example shows how when there are less than 11 pages to display that the previous, next, and all links are not shown

This example shows an alternate styling of the pagination results. By default a Digg-like CSS scheme is used however you can style the menu in limitless ways

Paginator.class.php
The paginator class allows you to easily generate page numbers and restrict database results without having to create complex pagination code of your own.
Features:
- Easy to use and reuse.
- Dynamically creates page numbers based on the total number of items in a query and the desired number of items per page.
- Ability to select a number of pages to display around the currently select page.
- Links to show all results instead of paginated results.
- Easily styled via CSS.
- Returns SQL which can be used to modify the results in query.
- The items per page can be changed by the user using a build in method which generates a simple drop down menu.
- A ‘jump to page’ menu can be generated to give the user quick access to jump to any page of the results.
- Creates ‘previous’ and ‘next’ buttons when more than 10 pages are generated.
Properties:
- $items_per_page – The desired number of items to be shown on a page. If you use this and the display_items_per_page method at the same time, it will override anything the user chooses from the drop down menu created by display_items_per_page.
- $items_total – The total number of items you’ll be paginating. Typically set by querying a table for a count of rows.
- $current_page – The page the user is viewing. Will always be an integer >= 1.
- $num_pages – The total number of pages as generated by the paginator method.
- $mid_range – The number of pages to show ‘around’ the current page. See step 5 in How To Use below.
- $low – The offset to use in a SQL LIMIT statement (e.g. SELECT * FROM employees LIMIT 20,10).
- $high – The number of rows to select in a SQL LIMIT statement (e.g. SELECT * FROM employees LIMIT 20,10).
- $limit – A string used in an SQL statement to automatically handle the limiting of results based on the current page of results.
- $return – A string used to store the HTML containing the page numbers.Used in the display_pages method.
- $default_ipp = 25 – The default number of items to display per page.
Methods:
- Paginator. Constructor. Usage:
$pages = new Paginator; - paginate. Calculates pages to display. Usage:
$pages->paginate(); - display_items_per_page. Returns a string of HTML used to display an items per page menu. Usage:
echo $pages->display_items_per_page(); - display_jump_menu. Returns a string of HTML used to display a page jump menu. Usage:
echo $pages->display_jump_menu(); - display_pages. Returns a string of HTML used to display the pages generated by the paginator
method. Usage:echo $pages->display_pages();
How to use:
- Include paginator.class.php at the top of your script
require_once 'paginator.class.php';Note: You could use include(), include_once(), or require() however using require_once ensures that the class will only be included once and if it can’t be found, will cause a fatal error. - Set the total number of items that you’ll be paginating.There are two ways to do this, 1) you can hard code the total, but that’s unrealistic since you’ll probably be using this class to paginate a database anyway (the whole point no?) but it can be a convenient way of testing or 2) make a quick call to your database to count the items you’ll be paginating. Ex: ‘SELECT COUNT(*) FROM table’ and save the total in a variable for use in step 4.
$pages->items_total = $num_rows; - Create a new Paginator object.
$pages = new Paginator; - Set the total items property of this new Paginator object.
$pages->items_total = Xwhere X is the total from step 2 - Set the mid range property.The mid range is the number of pages that the paginator will display, centered around and including the selected page. For example, if the mid range is set to seven ($pages->mid_range = 7;) then when browsing page 50 of 100, the mid range generates links to pages 47, 48, 49, 50, 51, 52, and 53. The mid range moves in relation to the selected page. If the user is at either the low or high end of the list of pages, it will slide the range toward the other side to accommodate the position. For example, if the user visits page 99 of 100, the mid range will generate links for pages 94, 95, 96, 97, 98, 99, and 100.
$pages->mid_range = X;where X is odd and >=3. The default mid_range property is 7. - That’s all for the configuration, now you can generate page numbers. To paginate, call the pagination method ($pages->paginate();). This generates no output so to show the page numbers call the display method ($pages->display_pages();).
You MUST call the paginate method before calling the display method. You can
call the display method more than once which can be handy for display page numbers both above and below a result set.echo $pages->display_pages(); - Optionally, you can give the visitor features in addition to what is provided by the display method.
- A drop down page jump menu is available via the display_jump_menu method (echo $pages->display_jump_menu();). This is a simple select menu that lists all page numbers. When a user changes the page number, the page will automatically switch to the selected page.
- A drop down items per page menu is available via the display_items_per_page method(echo $pages->display_items_per_page();). This select menu allows visitors to change the number of items that are displayed on a page. By default, the list it generates is 10, 25, 50, 100, All. You can modify the class if needed to allow for other options however the All options is case-sensitive. Note that the drop down menu that this creates will not work if you also set the $items_per_page property. Using both at the same time doesn’t really make sense anyway
- Once the paginate method has been called (see step 6), you can execute your db query to fetch the limited result set (or all results). Paginate creates the SQL used to limit results automatically so you can edit your query to take advantage of this. For example, if your query before pagination was
SELECT id, name, address FROM table ORDER BY id ASCyou would change it to beSELECT id, name, address FROM table ORDER BY id ASC $pages->limitWhen a user selects the ‘All’ option, they effectively set $pages->limit to nothing and any page selected automatically creates the appropriate limit.
$pages->limit - Styles. The pagination class has been created so that it can be styles with CSS easily. The recommended CSS is
<style type="text/css">
.paginate {
font-family: Arial, Helvetica, sans-serif;
font-size: .7em;
}
a.paginate {
border: 1px solid #000080;
padding: 2px 6px 2px 6px;
text-decoration: none;
color: #000080;
}
a.paginate:hover {
background-color: #000080;
color: #FFF;
text-decoration: underline;
}
a.current {
border: 1px solid #000080;
font: bold .7em Arial,Helvetica,sans-serif;
padding: 2px 6px 2px 6px;
cursor: default;
background:#000080;
color: #FFF;
text-decoration: none;
}
span.inactive {
border: 1px solid #999;
font-family: Arial, Helvetica, sans-serif;
font-size: .7em;
padding: 2px 6px 2px 6px;
color: #999;
cursor: default;
}
</style>
- Basic example:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1? />
<title>Paginator</title>
<style type=”text/css”>
.paginate {
font-family: Arial, Helvetica, sans-serif;
font-size: .7em;
}
a.paginate {
border: 1px solid #000080;
padding: 2px 6px 2px 6px;
text-decoration: none;
color: #000080;
}
a.paginate:hover {
background-color: #000080;
color: #FFF;
text-decoration: underline;
}
a.current {
border: 1px solid #000080;
font: bold .7em Arial,Helvetica,sans-serif;
padding: 2px 6px 2px 6px;
cursor: default;
background:#000080;
color: #FFF;
text-decoration: none;
}
span.inactive {
border: 1px solid #999;
font-family: Arial, Helvetica, sans-serif;
font-size: .7em;
padding: 2px 6px 2px 6px;
color: #999;
cursor: default;
}
</style>
</head>
<body>
<?php
require_once ‘paginator.class.php’;
// Make your database connection here and retrieve your total number of
items (i.e. SELECT COUNT(*) FROM…)
$pages = new Paginator;
$pages->items_total = $db_count;
$pages->mid_range = 7;
$pages->paginate();echo $pages->display_pages();
// Make your db query here. Include $pages->limit as described in step 8.
(i.e. SELECT id,fname,lname FROM employees $pages->limit)
echo $pages->display_pages(); // Optional call which will display the page numbers after the results.
echo $pages->display_jump_menu(); // Optional – displays the page jump menu
echo $pages->display_items_per_page(); //Optional – displays the items per
page menu
?>
</body>
</html>
All in all you could add pagination to any database driven set of results with about five lines of code. To display the current page number in the format ‘Page X of Y’ where X is the current page and Y is the total number of pages, use the code:
echo "<p class=\"paginate\">Page: $pages->current_page of $pages->num_pages</p>\n";
To display the SQL that was generated, use the code:
echo "<p class=\"paginate\">SELECT * FROM table $pages->limit (retrieve
records $pages->low-$pages->high from table - $pages->items_total item total / $pages->items_per_page
items per page)";
Nice Job! Paging was never simple as this before.
Very nice tutorial on developing digg like pagination. Thank you very much for this effort.
Very nice script. I have a suggestion: try not to directly use $_GET since most PHP frameworks now use SEO friendly URLs like example.com/page/1.
Very good script nonetheless.
Hi
i have written this but have no results, and i get this error message:
Notice: Undefined variable: option in C:\wamp\www\paginator_class\paginator.class.php on line 116
mysql_select_db($database_pagConn, $pagConn);
$query_rsSelectTotal = “SELECT COUNT(*) FROM persons”;
$thetotal = mysql_query($query_rsSelectTotal) or die(mysql_error());
$pages = new Paginator;
$pages->items_total = $thetotal;
$pages->mid_range = 7;
$pages->paginate();
echo $pages->display_pages();
$q2= “SELECT person_id,fname FROM persons $pages->limit”;
mysql_query($q2) or die(mysql_error());
echo $pages->display_pages();
echo $pages->display_jump_menu(); // Optional – displays the page jump menu
echo $pages->display_items_per_page(); //Optional – displays the items per page menu
echo “Page: $pages->current_page of $pages->num_pages\n”;
what am i doing wrong? this is very urgent for me.
best regards ron
I am like MM, Youri, James, and jm – I was not able to display my data set (I’m a PHP noobie, if you didn’t guess). So, in the section where I make my query (// Make your db query here. Include $pages->limit as described in step 8 – i.e. SELECT id,fname,lname FROM employees $pages->limit) I have the following (based on Soumik Dasgupta comment in #30 above):
$query = “SELECT * FROM movie $pages->limit”;
$movie_set = mysql_query($query, $connection) or die (“ERROR: $query.” . mysql_error());
$numofrows = mysql_num_rows($movie_set);
//and I added this:
echo “echo ” Title “;
while ($movie = mysql_fetch_array($movie_set)) {
echo “”;
echo $movie['MOVIE_TITLE'];
echo “”;
}
(This is a video database, so I’m showing titles of movies).
This works. However, based on admin’s comment in #45 above, I’m wondering if I’m doing this incorrectly. Any thoughts?
Thanks.
My added comments did not come through correctly. Here it is without any quotation marks (hopefully, this will work):
echo Title;
while ($movie = mysql_fetch_array($movie_set)) {
echo ;
echo $movie[MOVIE_TITLE];
echo ;
}
Sorry-still didn’t work. Table row and table header tags surround the Title in the first echo. Opening table row and table data tags in the second echo and closing table data and table row tags as well as a br tag in the final (4th) echo.
Sorry for the plethora of posts.
Thanks for the pagination class. It was simple to use, implement and execute.
Great results!
Thank you, I have made some modifications to this class so I’ll post a link to it, maybe some of you may find it useful.
Here you go: http://www.brilliantul.info/php/Paginator/Paginator_modified-v.1.0-brilliantul.zip
PS: it worked fine for me on several projects, it should work for you too.
Thanks for this excellent class! I am a PHP newbie and followed the example in #30 above. I am getting a few errors and was curious if any of you folks may be able to help me determine what I’m doing wrong?
Notice: Undefined index: ipp in C:\wamp\www\directory\paginator.class.php on line 25
Notice: Undefined index: page in C:\wamp\www\directory\paginator.class.php on line 35
Notice: Undefined index: page in C:\wamp\www\directory\paginator.class.php on line 84
Notice: Undefined index: page in C:\wamp\www\directory\paginator.class.php on line 88
Notice: Undefined index: page in C:\wamp\www\directory\paginator.class.php on line 89
Notice: Undefined index: ipp in C:\wamp\www\directory\paginator.class.php on line 100
Notice: Undefined index: ipp in C:\wamp\www\directory\paginator.class.php on line 101
Note – this appears above the table result and the pagination is placed below the table — appears to load OK save for the errors above.
Yr Script is totally bogus
as there is no poroper direction of displaying records.
it’s not woking…
I was going to just delete your comment but I figured that I’d leave it up here because it just makes you look silly. Do you honestly think that after all the comments and downloads for this class that it doesn’t work? Honestly. Or maybe do you think that the error is on your part?
i have problem using the class… it will display the correct number of pages but for every page all records will be displayed…
say i have 14 records in my table, i set the default_ipp to 5 in the class attribute… it will display 1 2 3 pages wc is correct but for every page all 14 records will be displayed. haiz.. wats wrong with this? please i badly need your help. tnx
Did you modify your SQL in step 8?
@admin
yes sir… i really don’t know wat’s wrong, please enlighten me
@admin
hahahaha… i already figured it out myself. tnx for dis class.. really cool. chill!
Muy buen trabajo.
Awesome! Thanks for the detailed directions and simple implementation. Just what I was looking for.
thanks a Million! it’s just Brilliant!
Great script, had been working on something similar but this is far better!
One problem I had
The page buttons carried forward some form data I didn’t want, eg if I had just added a record to my DB. I made the following changes to remove these extra form fields.
Hope someone finds this useful
When declaring the class (line 4+) added an ignore array
var $ignore = array(‘del’, ‘edited’);
Then I changed the parts which add the query string arguments to the page links, (the if($_GET) and if($_POST) functions)
if (in_array($keyval[0], $this->ignore)) {} else {
if($keyval[0] != “page” And $keyval[0] != “ipp”) $this->querystring .= “&” . $arg;
}
As for newbies who get this code hard to understand(those shifting from other pagination scripts) I found this comment http://www.catchmyfame.com/2007/07/28/finally-the-simple-pagination-class/#comment-557 easier to comprehend. Admin, please consider revising your comments to resemble the above code.
the script looks amazing….but i got the following error which i do not have a clue about…..
error
————
Notice: Undefined index: ipp in C:\wamp\www\mysite\includes\paginator.class.php on line 25
please help me out…
hi… i still can’t make this thing work ..can anyone please help me out..
Notice: Undefined index: ipp in C:\wamp\www\mysite\includes\paginator.class.php on line 32
Notice: Undefined index: offset in C:\wamp\www\mysite\includes\paginator.class.php on line 42
Notice: Undefined variable: option in C:\wamp\www\mysite\includes\paginator.class.php on line 130
Page: page:0 of 0
Retry the whole procedure again, are you sure you didnt make any changes to paginator.class.php, because mine goes upto line 125. (no line 130)
Hi!
When I click on ‘All’, it shows all records but it doesn’t highlight ‘All’. Instead of, ‘1′ is highlighted.
Can some one guide me how to solve this problem.
Thanks in advance
sumit :
These are Notices and in this case its because something hasn’t already been declared. e.g i set options = ”; before it is used, which removed that notice !!(Which was the only one i was getting)
e.g
function showJump()
{
$option = ”;
for($i=1;$inum_pages;$i++)
{
$option .= ($i==$this->current_page) ? “$i\n”:”$i\n”;
}
return “Page:Items$this->querystring’;return false\”>$option\n”;
}
works really really well. But the next and previous buttons don’t appear. Even with more then 10 items. Not sure why? Code is copied exactly. help!
@admin
Thanks for such a speedy response. i take it that you reuploaded your change?
I just want to applaud your efforts. I can’t image needing anything else in pagination?!?!?! i’m not going to bother looking for something to top this.
@admin
hmmm i still can’t get it to show the next prev – I tried ditching almost every bit of PHP on the page incase it was somehow dodging it up… didn’t fix it. I can’t figure it out! I downloaded your code again.
ahh got it to work.
on line 58 you have: if($this->num_pages > 10)
but it should be: if($this->num_pages > 1)
@doug
Actually you shouldn’t change that line and there are no images with the paginator class. I confused your post with a jquery plugin post.
great thanks for doing this? one question .. is there a security risk because the $_GET variables are not sanitized in the class file?
@Nate
Ah but they are. The class only accepts the string ‘All’ or numeric values via the is_numeric function. Anything else is cast as an int.
Very cool class. Except with E_ALL error reporting I get.
Notice: Undefined index: page in /home/usr/public_html/classes/class.pagination.php on line 93
Notice: Undefined index: page in /home/usr/public_html/classes/class.pagination.php on line 97
Notice: Undefined index: page in /home/usr/public_html/classes/class.pagination.php on line 98
Notice: Undefined index: ipp in /home/usr/public_html/classes/class.pagination.php on line 109
Notice: Undefined index: ipp in /home/usr/public_html/classes/class.pagination.php on line 110
This is becuase if someone visits the first page without the ?page or ?ipp in the url. $_GET['page'] and $_GET['ipp'] are undefined. But your hard referencing this these global variables on those lines in the class without checking if they are set.
You may want to fix that. I am quick fixing it myself….
Regards.
Here is my Quick fix those Notice: Undefined errors.
Add this to the class after the public (or rather ‘var’) variables are set.
[code]
public function __construct() {
if(empty($_GET['page']) || $_GET['ipp']){
$_GET['page'] = "";
$_GET['ipp'] = "";
}
}
[/code]
Excellent! This rocks!
Thanks for sharing.
I’ve coded my share of pagination scripts and even with my code tailored to suit my own needs, every implementation requires a fair amount of configuration. If this isn’t the most adaptable and easily implemented pagination script I’ve come across to date then I don’t know what is. Plug it in and go, what more could you ask for? Thank you for sharing this. It’s been a great learning tool as well an equally great paginator.
For those of you having problems, this script is flawless. If you take a look at the examples in the downloadable .zip file at the top of this page it will take all the guess work out of how and where to create objects, call methods, etc. if you are not already familiar with how this should be done.
thanks for sharing this amazing class..
Amazingly simple to use pagination class. Well done!
Is there a way to add some more variables to the query string that is attached to each pagination link?
@pixeline
Add as many variables as you like, the class simply passes them on for you to use in your script.
First thanks for the great code and sharing.
I ws getting the undefined error, like Keldorn and tried his fix. However I still get an, Undefined variable with the display_jump_menu…
$option .= ($i==$this->current_page) ? “$i\n”:”$i\n”;
How would I define that?
Thanks
Tim
okay scratch that, the fix above gets ride of the errors but I can not click through the pages. It just sits on page one.
Any thoughts for this newbie.
Thanks
Tim
Hello,
This class is simple perfect, one trouble I’m having now, is if I wanted to use more than one
pagination in a single page…
Is that a hard thing to make to use this class multiple times in the same page.
I already changed it to for use with more than english language, but this I’m a little bit lost,
how to get it working multiple times in the same page for different queries.
Best Regards,
I don’t know how to add other other variables to the query string attached to each pagination link. Please could anybody gives an example of this? Thanks
Does anyone have any idea about how easy it would be to integrate this with some crud class like AutoCRUD.php
This worked great! Thank you so much!
Okay new question, after figuring it out. Of course again Thank you for sharing and good vibes in your direction!
How can I make the top row, City Population, etc turn into a filter button. So, If I click population it would reset the list by desc population values and so on? Maybe too big of a question but still learning…Maybe if not easy to say then what to do research on, maybe a term or website…
Peace & Thanks!
Tim
I had the undefined problem as well and I added the code below and now I get this message.
Parse error: parse error, expecting `T_OLD_FUNCTION’ or `T_FUNCTION’ or `T_VAR’ or `’}” in D:\Production\CUPHD Production\h1n1db\paginator.class.php on line 16
Any ideas? I’m using IIS and PHP4.
Thanks
[code]
public function __construct() {
if(empty($_GET['page']) || $_GET['ipp']){
$_GET['page'] = "";
$_GET['ipp'] = "";
}
}
[/code]
Having issues with the script. I have everything set up according to the walk through, but it gives this error and am not sure how to fix it.
Fatal error: Unsupported operand types in inc/paginator.class.php on line 33
So I thought that it was the fact that the words or were used instead of the ||
I changed the two places where it said or in the code and am still getting that error. I am on PHP 5.2.11 if that helps.
I need help of how to use the class with postgres.
Great class though I would suggest makinga couplle changes in the class to aleviate people’s problems with the errors:
Change line 25 to:
if(isset($_GET['ipp']) && $_GET['ipp'] == ‘All’)
~ line 35 to
$this->current_page = isset($_GET['page']) ? (int)$_GET['page'] : 1; // must be numeric > 0
~ Line 41 to
if(isset($_GET) && is_array($_GET))
~line 51 to
if(isset($_POST) && is_array($_POST))
~84 to
$this->return .= ($i == $this->current_page && isset($_GET['page']) && $_GET['page'] != ‘All’)…
~88 to
$this->return .= (($this->current_page != $this->num_pages && $this->items_total >= 10) && isset($_GET['page']) && ($_GET['page'] != ‘All’))….
~89 to
$this->return .= (isset($_GET['page']) && $_GET['page'] == ‘All’)….
(there’s more though…)
For Everyone getting ‘Unsupported operand types’ it’s likely because you are passing an array to the class for items_total. Try:
$pages->items_total = intval($num_rows[0][0]);
I have error reporting turned all the way up so that I can be sure my projects are more likely to work when i move them from dev to production servers on different environments. It has made me a cleaner code.
Also I’m not sure why you continue to reference $_GET and $_POST throughout the class. It seems you should set those values in the Paginator constructor function and continue to reference the $this->variable throughout the rest of the class.
I’ll likely make my changes and post them on my blog – please shoot me an email if you’d like me to email the update to you as well for you to update here on your site