Sat 28 Jul 2007
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.
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. Can be set by the script author or user
- $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
code: 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.
- Create a new Paginator object.
code: $pages = new Paginator; - Set the total items property of this new Paginator object.
code: $pages->items_total = X where X is the total from see 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.
code: $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.
- 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 ($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
($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.
- 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 ASC”, you would change it to be “SELECT id, name, address FROM table ORDER BY id ASC $pages->limit”. When a user selects the ‘All’ option, they effectively set $pages->limit to nothing and any page selected automatically creates the appropriate limit.
code: $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 pages
number 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)”;
July 28th, 2007 at 10:42 pm
Definitely has the Digg style but I just downloaded and tried and it worked great. Very easy to implement. Good worK!
September 18th, 2007 at 11:10 am
[...] wanted to make a small addition to the pagination class talked about at http://www.catchmyfame.com/2007/07/28/finally-the-simple-pagination-class/. I added another example which uses a basic form at [...]
November 10th, 2007 at 8:18 pm
Thank you!
November 16th, 2007 at 1:29 pm
Excellent, the Paginator/Pagination class makes perfect sense.
The only thing missing (not so much missing, but as a very nice feature that could be added) is to have a way to sort by clicking on the headers.
This additional ‘Sorter/Sorting Class’ would sort the entire query and most likely reset the page pointer back to page 1. There could also be a ‘quick sort column’ or ’sort this page by column’ feature where the sorting most likely would be implemented in javascript and the sorting would be for that specific page only, still keeping the original query and the current page number. For the client side sorting I’d recommend tablesorter, a jQuery plugin http://tablesorter.com/docs/ for individual page sorting keeping. While a Sorter Class would do the server side sorting heavy lifting from your database.
The relation of whether the sorter class wraps the pagination class, in the form of a private member (as used in a similar way to a java’s static Class), or pagination class implemnents the sorting class, or thirdly, you could extend the pagination class and created a SortingPagination class, whichever way its probably more of a personal preference, how elegant, and how coupled or bloated you want the classes to be.
I try not to fall into the trap of overdesigning as things tend never to leave the design stage to be implemented at all.
December 1st, 2007 at 10:37 pm
I’m a php OOP newbie. Can you give me a more detailed example of how I would make the db query for step number 8?
Thanks.
December 2nd, 2007 at 12:16 pm
Never mind, I figured out my mistake. Tremendous thanks for sharing this amazing class.
December 21st, 2007 at 3:03 am
[...] Catch My Fame » Finally, the simple pagination class [...]
January 12th, 2008 at 2:29 am
Thanks for information.
many interesting things
Celpjefscylc
January 14th, 2008 at 8:55 pm
That is an awesome class. Manny thanks for sharing! Greetings from eastern europe
January 21st, 2008 at 1:21 pm
I’m not a programmer but managed to get it to work with my oscommerce site. Only took me a day :)I do have 1 prob tho. When I pick All, I get error in my SQL. It’s the end limit, it is blank. Tried if_null, empty etc but still not working. Great class so I’ll keep plugging away.
January 21st, 2008 at 2:56 pm
Solved. On line 101 of the pagination class had to change
LIMIT $this->low,$this->items_per_page”;
to
LIMIT 0,$this->items_per_page”; //That’s a zero
For me, the limit was coming out as -25,25 which oscommerce or MYSQL, whichever, doesn’t like. Hehe, I sound like a programmer now.
Now, displaying items 1 to 25 (of 100), how to do that???
January 23rd, 2008 at 4:24 am
Hi all,
I need ur help,
how I would make the db query for step number 8?
because , I have this error messages:
Undefined index: ipp
Undefined index: page
Thanks for ur help
and this is my Code:
items_total = 5;
$pages->mid_range = 7;
$pages->paginate();
echo $pages->display_pages();
echo “Page: $pages->current_page of $pages->num_pages\n”;
echo “SELECT * FROM offres $pages->limit (retrieve records $pages->low-$pages->high from table - $pages->items_total item total / $pages->items_per_page items per page)”;
echo $pages->display_jump_menu();
?>
January 23rd, 2008 at 7:06 pm
@Ianric - I’m not sure what’s going on with your instance of the paginator but the lower limit should never be lower than zero. The line if($this->current_page current_page)) $this->current_page = 1; should ensure that.
@BOB - I’d need more information to figure out your issue. email me at admin@catchmyfame.com.
January 25th, 2008 at 10:09 pm
greatings…
usefull…
February 4th, 2008 at 7:54 am
Hello, I first want to say thank you very much for sharing this. Even with my very limited php skills i’ve managed to implement this with minimal effort. If you have a few moments I do have one quick question i’m hoping you may be able to help me with.
I’ve modified the class a wee bit to produce a URL like:
page.php?cat=shoes&page=5
for mod rewriting purposes down the line and it works a treat. I can’t seem to add another variable to the querystring though. What i’m trying to do is add a sub-category so the link would look something like:
page.php?cat=shoes&size=small&page=5
instead what I get is:
page.php?cat=shoessize=small&page=5
I’ve made an (laughable) attempt to resolve this one but i’ve not had any luck. Is this feasible?
Thanks again!
February 5th, 2008 at 11:18 pm
It appears that i’ve posted too soon. After a bit of trial and error I managed to figure it out. Thank you again for sharing this!
Regards.
March 1st, 2008 at 1:52 pm
For the longest time this would not work for me. Then I noticed, where in step 2 you set $pages->item_total = X, it is actually $pages->items_total.
Also, near line 104/105, you get undefined notices. I’ve cleared those up using this…
$this->high = ((!empty($_GET['ipp'])) && ($_GET['ipp'] == ‘All’)) ? $this->items_total:( $this->current_page * $this->items_per_page ) -1;
$this->limit = ((!empty($_GET['ipp'])) && ($_GET['ipp'] == ‘All’)) ? “”:” LIMIT $this->low, $this->items_per_page”;
March 12th, 2008 at 5:19 am
Hi, could someone help me out. I am trying to figure out the line of code that i need to insert into my page for all my results from my query to be displayed. i can get the script to recognize having 1 page, but no data gets displayed.
thanks!
March 23rd, 2008 at 5:37 pm
i had the same problem as Ianric did.
Basically i believe it is the number of records in DB caused the error.
when you have, say 5 records, you get something limit -25, 25.
haven’t had time to check this. but it definitely a bug.
nice class. thx.
April 1st, 2008 at 5:03 pm
If you follow the advice in #17 you likely wont need to follow the advice in #11.
April 23rd, 2008 at 11:39 am
I’m not a complete newbie at PHP but just starting to use/edit classes.
This is just what I was looking for, so credits for that.
But somehow I can’t display my query’s. I have read the documentary twice but I can’t find the way how to do that!
Is there please someone who can help me with this?
May 4th, 2008 at 5:02 am
It works! But my result set has 12 items. When I choose 10 ipp, i get 3 pages?? That’s 1 page too much.
I followed the steps in 17.
Does somebody have a clue?
May 5th, 2008 at 3:27 pm
For those who still get a -25,25 error here is the fix
Open the class and go to line 99
add this to line 100
if ($this->low low = 0;
}
should do it
May 5th, 2008 at 3:27 pm
if ($this->low low = 0;
}
May 5th, 2008 at 3:28 pm
if ($this->low low = 0; }
May 5th, 2008 at 3:33 pm
looks like it keeps stripping the code
here is a link to the changes
http://www.daemonprojects.com/pageclassupdate.txt
May 6th, 2008 at 1:20 am
Sorry, the code doesn’t provide the solution to my problem.
I used your link to c&p the code, but my problem remains.
I have 12 records as a result from the query out of my DB.
When I choose 10 items per page from the optional pulldown menu, I get 3 pages…
first page shows the first 10 records from the result.
second page shows the next 2 records.
and the third page is empty.
The query from my count is exactly the same as the query for my result-set of records.
I looked trough the code a couple of times, but can’t lay my finger on it…..
May 7th, 2008 at 5:50 pm
How can I make this work with an huge array?
require_once ‘paginator.class.php’;
$pages = new Paginator;
$pages->items_total = $db_count;
$pages->mid_range = 7;
$pages->paginate();
echo $pages->display_pages();
What do I need to add to the foreach of the array to make it paginate?
ie: foreach($pagenate as $row)…
echo $pages->display_pages();
echo $pages->display_jump_menu();
echo $pages->display_items_per_page()
May 18th, 2008 at 2:46 am
I’m a php OOP newbie. Can you give me a more detailed example of how I would make the db query for step number 8?
June 12th, 2008 at 1:57 am
Hi uma,
You need to call the DB twice. One to determine the total number of pages WITHOUT LIMIT and secondime with $pages -> limit at the end of the SQL.
Here is what I used and worked fine:
//Get all students under this profile for pagination
$sql_get_students = “SELECT * FROM WHERE user_id = $user_id ORDER BY `student_id` DESC”;
$result_sql_get_students = mysql_query($sql_get_students, $link) or die(mysql_error($result_sql_get_students));
$numofrows = mysql_num_rows($result_sql_get_students);
//Genrate the pagination
$pages = new Paginator;
$pages->items_total = $numofrows;
$pages->mid_range = 4;
$pages->paginate();
$sql_get_students = “SELECT * FROM students WHERE user_id = $user_id ORDER BY `student_id` DESC $pages->limit”;
$result_sql_get_students = mysql_query($sql_get_students, $link) or die(mysql_error($result_sql_get_students));
$numofrows = mysql_num_rows($result_sql_get_students);
June 13th, 2008 at 10:04 am
Wow so simple and powerful.
thank you for sharing this amazing class..
June 24th, 2008 at 7:08 pm
Just what I was looking for. Be sure to read comment #17 so it works. Would be nice if this was updated to solve the bug, because if you don’t read the comments, it might take awhile to get it working…
June 30th, 2008 at 9:59 pm
So, forgive my noobness…
What query should I make to show all info from table “abc”, for example?
Please and thanks!!
July 24th, 2008 at 10:49 am
[...] with forms, and is cake to use. I just implemented it in a project and saved a half a days work.http://www.catchmyfame.com/2007/07/28/finally-the-simple-pagination-classFAN-TASTIC ENDLESS BREEZE 12V FANS by Fantastic Vent - 22-0102Read Reviews & Compare Price for [...]
August 7th, 2008 at 1:07 pm
My start page is “index.php?site=news&page=page1″ How I can use paginator?
Tx
August 31st, 2008 at 5:02 am
Just to help people out — I was also getting the SQL errors with the -25/25 LIMIT. After a few minutes of hair pulling and debugging, I realized it was because I copiped n’ pasted from #4 in the instructions.
The instructions read: $pages->item_total
This should be: $pages->items_total
Notice the ’s’ in ‘items’. It should be plural. So, out of curiosity, I wonder if those other complaints above originate from the same accidental copy n’ paste from the instructions.
Regardless… really great class bro. I’ll def. give it some usage in the future.
September 4th, 2008 at 9:29 am
Good catch Icaurs, I missed that typo. Fixed.
September 18th, 2008 at 6:07 am
Fantastic class, very well designed and so easy to implement.
Thanks !!
September 24th, 2008 at 5:19 pm
You think that we could get a fully working version of this… with downloadable source (both class and example paging.php) It would be much appreciated by myself I know and I’m sure anyone else that is going to try and use this.
Thanks
September 24th, 2008 at 8:39 pm
The class is available for download at the top of this post. What else do you need?
September 25th, 2008 at 11:30 am
I’m new to the server side and being able to see the actual php and mysql connections helps me learn. So instead of seeing:
/ Make your db query here. Include $pages->limit as described in step 8.
(i.e. SELECT id,fname,lname FROM employees $pages->limit)
in your explanation, it helps me more to see how the actual example.php code looks/works (with your database details removed of course). So my suggestion would be a link to the example.php code (plain text) next to the link to see it in action.
Admin I really appreciate what you’ve done for all of us in posting this class, and I don’t want to be a pest. I’m just trying to help improve your helping others (along with myself;-)
Thanks
September 29th, 2008 at 10:05 pm
Hi there,
I am using your pagination class, very helpful indeed. I have a small problem though. On my website pagination always limit itself to 14 pages. Max is always 14, eventhough recordset returns data for 75 pages. Is there anything i am missing? It would be great if you can email me. Thanks a lot for the great class.
September 29th, 2008 at 10:25 pm
Please ignore the previous post. It turned out I called the wrong variable.
October 9th, 2008 at 1:48 am
Hi,
sorry, I’m new to php and I don’t quite understand your point #8 and what part of the code exactly is responsible for displaying the chunk of result set. All I get is the (correct) number of page links displayed and no data. Shouldn’t I somehow tell paginator what the actual query is?
Thanks for your patience.
October 9th, 2008 at 1:36 pm
Actually the class tells your query what to do. Step 8 explains how to modify your query to use paginator to limit the results. Run through all the steps and check out step 10 for a basic example.
November 17th, 2008 at 8:42 pm
Just got around to finally using this class in a live site. I made some changes to the class file to make it’s 100% XHTML complaint. Minor stuff. Just drop me a note in email and I’ll send it over. Again, nice class.