I’ve had a few pagination scripts over the years but I thought i’d share the one that i’m currently using as it’s a useful script to have in your toolbox. As a developer you’ll soon find a need to paginate data when displaying contents from the database, and rather than use JavaScript which could require all the data to be loaded into the page on load, we can use PHP to ensure that we’re only requesting the data that we need from the database. For those who have no clue what i’m talking about. Pagination is a way of splitting up data into manageable chunks to display to a user, if you’ve spent more than two minutes on the internet chances are you’ve come into contact with some form of pagination. as a simple example you can checkout my homepage, at the bottom you’ll see a list of page numbers allowing you to browse through pages of data, this script was originally written by the guys over at Stranger Studios and allows you to split data up with it being paginated across however many pages dynamically.

To start with you’ll see that we have our database connection file which we’re including into the page. Next you’ll see we’re setting three variables. ‘$tableName’, this refers to the table in your database that you want to get the data from, in our case it’s ‘countries_list’, ‘$targetpage’ refers to whatever you’ve saved the file as, in the case of the demo we’re saving the file as ‘index.php’. ‘$limit’ is the number of rows per page that we want to display from the database in the case of the demo you’ll see that we’re displaying just 10 rows.
Here are the main bullet points of what this file does in the simplest form.
<?php
include('connect.php');
$tableName="countries_list";
$targetpage = "index.php";
$limit = 10;
$query = "SELECT COUNT(*) as num FROM $tableName";
$total_pages = mysql_fetch_array(mysql_query($query));
$total_pages = $total_pages[num];
$stages = 3;
$page = mysql_escape_string($_GET['page']);
if($page){
$start = ($page - 1) * $limit;
}else{
$start = 0;
}
// Get page data
$query1 = "SELECT * FROM $tableName LIMIT $start, $limit";
$result = mysql_query($query1);
// Initial page num setup
if ($page == 0){$page = 1;}
$prev = $page - 1;
$next = $page + 1;
$lastpage = ceil($total_pages/$limit);
$LastPagem1 = $lastpage - 1;
$paginate = '';
if($lastpage > 1)
{
$paginate .= "<div class='paginate'>";
// Previous
if ($page > 1){
$paginate.= "<a href='$targetpage?page=$prev'>previous</a>";
}else{
$paginate.= "<span class='disabled'>previous</span>"; }
// Pages
if ($lastpage < 7 + ($stages * 2)) // Not enough pages to breaking it up
{
for ($counter = 1; $counter <= $lastpage; $counter++)
{
if ($counter == $page){
$paginate.= "<span class='current'>$counter</span>";
}else{
$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
}
}
elseif($lastpage > 5 + ($stages * 2)) // Enough pages to hide a few?
{
// Beginning only hide later pages
if($page < 1 + ($stages * 2))
{
for ($counter = 1; $counter < 4 + ($stages * 2); $counter++)
{
if ($counter == $page){
$paginate.= "<span class='current'>$counter</span>";
}else{
$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
}
$paginate.= "...";
$paginate.= "<a href='$targetpage?page=$LastPagem1'>$LastPagem1</a>";
$paginate.= "<a href='$targetpage?page=$lastpage'>$lastpage</a>";
}
// Middle hide some front and some back
elseif($lastpage - ($stages * 2) > $page && $page > ($stages * 2))
{
$paginate.= "<a href='$targetpage?page=1'>1</a>";
$paginate.= "<a href='$targetpage?page=2'>2</a>";
$paginate.= "...";
for ($counter = $page - $stages; $counter <= $page + $stages; $counter++)
{
if ($counter == $page){
$paginate.= "<span class='current'>$counter</span>";
}else{
$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
}
$paginate.= "...";
$paginate.= "<a href='$targetpage?page=$LastPagem1'>$LastPagem1</a>";
$paginate.= "<a href='$targetpage?page=$lastpage'>$lastpage</a>";
}
// End only hide early pages
else
{
$paginate.= "<a href='$targetpage?page=1'>1</a>";
$paginate.= "<a href='$targetpage?page=2'>2</a>";
$paginate.= "...";
for ($counter = $lastpage - (2 + ($stages * 2)); $counter <= $lastpage; $counter++)
{
if ($counter == $page){
$paginate.= "<span class='current'>$counter</span>";
}else{
$paginate.= "<a href='$targetpage?page=$counter'>$counter</a>";}
}
}
}
// Next
if ($page < $counter - 1){
$paginate.= "<a href='$targetpage?page=$next'>next</a>";
}else{
$paginate.= "<span class='disabled'>next</span>";
}
$paginate.= "</div>";
}
echo $total_pages.' Results';
// pagination
echo $paginate;
?>
<ul>
<?php
while($row = mysql_fetch_array($result))
{
echo '<li>'.$row['country'].'</li>';
}
?>
</ul>
Here’s the css to style you pagination
.paginate {
font-family:Arial, Helvetica, sans-serif;
padding: 3px;
margin: 3px;
}
.paginate a {
padding:2px 5px 2px 5px;
margin:2px;
border:1px solid #999;
text-decoration:none;
color: #666;
}
.paginate a:hover, .paginate a:active {
border: 1px solid #999;
color: #000;
}
.paginate span.current {
margin: 2px;
padding: 2px 5px 2px 5px;
border: 1px solid #999;
font-weight: bold;
background-color: #999;
color: #FFF;
}
.paginate span.disabled {
padding:2px 5px 2px 5px;
margin:2px;
border:1px solid #eee;
color:#DDD;
}
li{
padding:4px;
margin-bottom:3px;
background-color:#FCC;
list-style:none;}
ul{margin:6px;
padding:0px;}
I applied this code.since display data is displayed only the data from the first page (lines <limit). So the following pages do not display anything
can you help me please
thank you for the tutoriels
Thank you SO SO SO SO much! This was a HUGE help, and I really appreciate you posting this! Best pagination I’ve seen
Thanks a lot…..
you make pagination problem simple and easier for me…..
now no tension for placing pagination ….
thanx once again
Hi,
This is Great and simple script…Thanks for sharing it.
If i need to add ‘first and last’ option before and after ‘previous and next’ button, what will be the changes in code??
Hi,
When I call the page with the pagination from a form submit, the query (select statement) is built from the form data.
The first page and count is correct but If I click on any of the page navigation #s or next/previous, the select statement is not stored between and the results defaults to all records.
Any ideas on how to prevent this?
Thanks.
Thank You so much ! been so useful and easy to use this pagination code !
Thanks again
very nice post dude thanks ……
This is THE easiest and simplest tutorial I’ve seen on pagination till date.
Awesome job man! Works like a charm and super easy to plug in.
Here is my version of pagination, if you go to http://www.jadremtoys.com.au/catalogue/toy-group.php?grpid=141&name=Barbie-Collector you’ll see the the “grpid = 141″ this paramater is used in the $tableName=”view_catgrpitemlist”
1)
{
$paginate .= “”;
// Previous
if ($page > 1){
if ($page ==2 ){
$paginate.= “previous“;
}else{
$paginate.= “previous“;
}
}else{
$paginate.= “previous”; }
// Pages
if ($lastpage < 7 + ($stages * 2)) // Not enough pages to breaking it up
{
for ($counter = 1; $counter <= $lastpage; $counter++)
{
if ($counter == $page){
$paginate.= "$counter”;
}else{
if ($counter ==1 ){
$paginate.= “$counter“;
}else{
$paginate.= “$counter“;
}
}
}
}
elseif($lastpage > 5 + ($stages * 2)) // Enough pages to hide a few?
{
// Beginning only hide later pages
if($page < 1 + ($stages * 2))
{
$paginate.= "1“;
for ($counter = 2; $counter < 4 + ($stages * 2); $counter++)
{
if ($counter == $page){
$paginate.= "$counter”;
}else{
$paginate.= “$counter“;
}
}
$paginate.= “…”;
$paginate.= “$LastPagem1“;
$paginate.= “$lastpage“;
}
// Middle hide some front and some back
elseif($lastpage – ($stages * 2) > $page && $page > ($stages * 2))
{
$paginate.= “1“;
$paginate.= “2“;
$paginate.= “…”;
for ($counter = $page – $stages; $counter <= $page + $stages; $counter++)
{
if ($counter == $page){
$paginate.= "$counter”;
}else{
$paginate.= “$counter“;
}
}
$paginate.= “…”;
$paginate.= “$LastPagem1“;
$paginate.= “$lastpage“;
}
// End only hide early pages
else
{
$paginate.= “1“;
$paginate.= “2“;
$paginate.= “…”;
for ($counter = $lastpage – (2 + ($stages * 2)); $counter <= $lastpage; $counter++)
{
if ($counter == $page){
$paginate.= "$counter”;
}else{
$paginate.= “$counter“;
}
}
}
}
// Next
if ($page < $counter – 1){
$paginate.= "next“;
}else{
$paginate.= “next”;
}
$paginate.= “”;
}
echo $total_pages.’ Results’;
// pagination
echo $paginate;
?>
Hi David, yes it can be done, go to our childrens toys site http://www.jadremtoys.com.au. The category menu on the left will deliver paginated results, a menu is just like a search it provides the database with a parameter
Cheers
Sam
Thanks for a great tutorial! When I do a search and paginate the results everything looks great. When I click on any of the paginated pages, though, the whole database is returned. Is there anyway to paginate through a found set that was based on a search from a form input?
Thanks,
David
When first time browse i got this error “Notice: Undefined index: page in” if click pagination it’s disapper
“Notice: Undefined index: page in” first time browse how can i fix it
thanks for sharing… It really helped me to get rid of headache, caused to do pagination.
Code needs slight change, just ran MS site analysis report over my site, it picks up the initial page say “catalogue” and when you go back and via the paginator to page 1 the href is catalogue&page=1.
Site analysis reports it as a multiple canonical, catalogue and catalogue&page=1 being the same page.
When we go back to page one it should drop the page=1
cheers
If you want the pagination images at the bottom of your list just move the code for the repeating loop above the pagination code
http://www.jadremtoys.com.au/catalogue/toy-group.php?grpid=101&name=Action-Figures-And-Toys
cheers
Very much appreciated, had to play around a bit suit our needs – works well looks good
http://www.jadremtoys.com.au/catalogue/toy-group.php?grpid=99&name=Music-Boxes
Cheers
Sam
Thanks for sharing. u very helpful.Excellent
A great stuff..a simple and easy way to handle pagination .Thanks for the article.
Nicely done. one thing i like to ask. how can i add the pagination to bottom of the page? thanks
Hi,
The form that i am using is on a different page eg testpage and the results are to be displayed on testresults .. when submit is clicked the first testresults page is fine but then the links do not work.
i am guessing ths is because of
$page = mysql_escape_string($_GET['page']);
any advice will be helpful?
Hi ashley,
Thanks for the great post.. However, im getting this error.. dont know why.. see below
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\PHP\pagination\index.php on line 67
Notice: Use of undefined constant num – assumed ‘num’ in C:\PHP\pagination\index.php on line 68
Notice: Undefined index: page in C:\PHP\pagination\index.php on line 71
Results
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\PHP\pagination\index.php on line 187
It refers to this line
$total_pages = $total_pages[num];
and this line
$page = mysql_escape_string($_GET['page']);
Im confused.. Help please.. thanks ashley..
Excellent, thanks!
Thatś great, I’m changing my script from Wp to a mine from the scracth and comes perfect this pagination, thank you for the tutorial!
This Is The Best Class I Ever So
Thanks For Sharing
How Can I Make The Number Show
Right To Left
Instead Of
Left To Right ?
display records from dbase page wise in php, page numbers should be displayed in a drop down combo box (using ). instead of like this: page numbers 1, 2, 3, …. till last.
Thanks for this awesome solution . Great tut.
Thanks. Very nice tutorial.
Thanks so much!
absolutely great and easiest tutorial in the whole net. I needed one and here it is in my website you can check the result http://www.turkishpropertiesabroad.com
it paginates the houses…
Thanx Man
amazing and easy pagination , hats off
Thanks Ashley, the code worked perfect. Only one question, when I changed the SQL query to $query = SELECT COUNT(*) as num FROM $tableName order by ID DESC it didn’t work. Please let me know how to fix this. The results are displayed random because of this.
Again Thanks
hi i have used your script and when there are more than 10 results it displays a link to the next page but there are more than 10 results appearing on the page and the same results on the second page without splitting them, any help with this problem please
Hello,
Just downloaded the files and they are corrupt also when viewing this website I get the code displayed ina funny way.
<?php
002 include(‘connect.php’);
003
004 $tableName="countries_list";
005 $targetpage = "index.php";
006 $limit = 10;
007
008 $query = "SELECT COUNT(*) as num FROM $tableName";
009 $total_pages = mysql_fetch_array(mysql_query($query));
010 $total_pages = $total_pages[num];
011
012 $stages = 3;
013 $page = mysql_escape_string($_GET['page']);
014 if($page){
015 $start = ($page – 1) * $limit;
016 }else{
017 $start = 0;
018 }
019
020 // Get page data
021 $query1 = "SELECT * FROM $tableName LIMIT $start, $limit";
022 $result = mysql_query($query1);
023
024 // Initial page num setup
025 if ($page == 0){$page = 1;}
026 $prev = $page – 1;
027 $next = $page + 1;
028 $lastpage = ceil($total_pages/$limit);
029 $LastPagem1 = $lastpage – 1;
030
031 $paginate = ”;
032 if($lastpage > 1)
033 {
034
035 $paginate .= "<div class=’paginate’>";
036 // Previous
037 if ($page > 1){
038 $paginate.= "<a href=’$targetpage?page=$prev’>previous</a>";
039 }else{
040 $paginate.= "<span class=’disabled’>previous</span>"; }
041
042 // Pages
043 if ($lastpage < 7 + ($stages * 2)) // Not enough pages to breaking it up
044 {
045 for ($counter = 1; $counter <= $lastpage; $counter++)
046 {
047 if ($counter == $page){
048 $paginate.= "<span class=’current’>$counter</span>";
049 }else{
050 $paginate.= "<a href=’$targetpage?page=$counter’>$counter</a>";}
051 }
052 }
053 elseif($lastpage > 5 + ($stages * 2)) // Enough pages to hide a few?
054 {
055 // Beginning only hide later pages
056 if($page < 1 + ($stages * 2))
057 {
058 for ($counter = 1; $counter < 4 + ($stages * 2); $counter++)
059 {
060 if ($counter == $page){
061 $paginate.= "<span class=’current’>$counter</span>";
062 }else{
063 $paginate.= "<a href=’$targetpage?page=$counter’>$counter</a>";}
064 }
065 $paginate.= "…";
066 $paginate.= "<a href=’$targetpage?page=$LastPagem1′>$LastPagem1</a>";
067 $paginate.= "<a href=’$targetpage?page=$lastpage’>$lastpage</a>";
068 }
069 // Middle hide some front and some back
070 elseif($lastpage – ($stages * 2) > $page && $page > ($stages * 2))
071 {
072 $paginate.= "<a href=’$targetpage?page=1′>1</a>";
073 $paginate.= "<a href=’$targetpage?page=2′>2</a>";
074 $paginate.= "…";
075 for ($counter = $page – $stages; $counter <= $page + $stages; $counter++)
076 {
077 if ($counter == $page){
078 $paginate.= "<span class=’current’>$counter</span>";
079 }else{
080 $paginate.= "<a href=’$targetpage?page=$counter’>$counter</a>";}
081 }
082 $paginate.= "…";
083 $paginate.= "<a href=’$targetpage?page=$LastPagem1′>$LastPagem1</a>";
084 $paginate.= "<a href=’$targetpage?page=$lastpage’>$lastpage</a>";
085 }
086 // End only hide early pages
087 else
088 {
089 $paginate.= "<a href=’$targetpage?page=1′>1</a>";
090 $paginate.= "<a href=’$targetpage?page=2′>2</a>";
091 $paginate.= "…";
092 for ($counter = $lastpage – (2 + ($stages * 2)); $counter <= $lastpage; $counter++)
093 {
094 if ($counter == $page){
095 $paginate.= "<span class=’current’>$counter</span>";
096 }else{
097 $paginate.= "<a href=’$targetpage?page=$counter’>$counter</a>";}
098 }
099 }
100 }
101
102 // Next
103 if ($page < $counter – 1){
104 $paginate.= "<a href=’$targetpage?page=$next’>next</a>";
105 }else{
106 $paginate.= "<span class=’disabled’>next</span>";
107 }
108
109 $paginate.= "</div>";
110
111 }
112 echo $total_pages.’ Results’;
113 // pagination
114 echo $paginate;
115 ?>
116
117 <ul>
118
119 <?php
120
121 while($row = mysql_fetch_array($result))
122 {
123
124 echo ‘<li>’.$row['country'].’</li>’;
125
126 }
127
128 ?>
129 </ul>
Thats the code I get when viewing, does anyone have an ammended version to this please.
My email is qakbar@hotmail.co.uk
Thank you
Nice Post dude
thank u soo much .its working perfectly
great stuff, but how would you link in a search form?
Thanks a lot. You saved my day.
Hello.I optain the “Notice: Undefined index: page in C:\wamp\www\top50brands\index.php on line 13″
What its wrong?
ya i am new to php and html … can some explain why these “"countries_list"” are part of every single line …. does that not confused developer …
Thanks for this. It is working very well
Hey dude,
its a great site.. Each of the contents are quite intresting. well done dude..
Thx a lot Ashley it worked perfectly
Fantastic script, works perfectly, thanks for that.
That’s exactly what I was looking for!
Thanks for this, works perfectly and is by far the easiest to use!!!
good but nit great there are some bugs
Easy? I don’t find this to really be much easy I guess since I’ve been using a php mvc framework for about 4 months now. It’s a great post and I thank you for your contribution. Here’s something others might want to look at using MVC frameworks.
// function to call
function get_limit_and_offset($per_page, $page_number)
{
if($page_number < 1)
{
$page_number = 1;
}
$pagination['limit'] = $per_page;
$pagination['offset'] = ($page_number * $per_page) - $per_page;
return $pagination;
}
// give function data
$pagination_data = get_limit_and_offset($per_page, $page_number);
// query thats used
mysql_query("SELECT * FROM `$table_name` LIMIT $perpage OFFSET $page_num");
تسلم ايدك ونتمنى لك التوÙيق
مشكور الك
Nice definatly the best one i have found so far but whats the best way to display less links, i only want to show like 3-5 links maximum and the lowest i can seem to get it with your script is 7 -9 and i dont have enough room.
Pingback: Three Easy Steps to Becoming a Video Game Tester | Games Testing Ground
Hey, this is a great tutorial! I’ve got it all working, but I want to sort my results by the date the data was submitted to the database. I’ve changed the query to SELECT * FROM dream ORDER BY `date_entered` DESC but it doesn’t seem to work, anybody know why?
Any help would be greatly appreciated, thanks, Adam.
Pingback: Easy PHP Pagination - Solution Expert Online Blogs
It would be very cool if you had created a simple .htaccess to display pretty URLs
Nice tutorial
You should isolate pagination logic into it’s own class. This code is hard to reuse compared to something like:
$pagenav = new pagenav($_REQUEST['p'], 10, $count['total'], ‘documents.php?do=overview’);
Then the object will calculate the LIMIT values based on the parameters you pass in:
LIMIT $pagenav->lower, $pagenav->upper
Then of course you can render your pagenav using:
$pagenav->render()
I really should get around to publishing a few of these utility classes I’ve wrote. I hope it will encourage you to consider doing this for your example
What if I don’t want to paginate “everything”?
What if I only want the results of a users search using an advanced search form?
What if that form page submits to this paginated Results page which then builds sql for the users desired query and paginates the results?
When they click on the “next page” how is the sql given to the next page when the sql doesn’t exist hard coded into this results page?
What if several sections of my site are like this and all use different tables?
What if to address the issue of passing the dynamically generated user query from one page to the next I chose to switch to having the page number in a select in a form with hidden fields containing the users original choices so that they could be posted to the next page resulting in the exact same base sql being created for the next page? I’d have to make a lot of edits that aren’t directly related to the act of pagination in a region of code full of pagination related code.
I think it would be better to separate the display of page number links (and any display logic involved) into a separate template-like file that gets included after the main pagination & query stuff happens.
(My personal pagination _class_ is simultaneously MUCH worse AND MUCH MUCH MUCH better.)
$sql = “SELECT * FROM tblcountry $dynamicWhereClause ORDER BY cTitle ASC”;
$pgn8 = new pagination($sql, 20); // 20 items per page
echo $pgn8->showingFromTo(); // Showing 121 – 135 of 1592 Results Found
$page_result = $pgn8->findPageResult();
echo $links = $pgn8->displayPagination(‘pgn8-.tpl’);
// show clickable page numbers before result list using one of the non-default markup template files (maybe this one uses roman numerals?)
while($row = mysql_fetch_assoc($page_result))
{ loop through and display rows data as list items or table rows etc }
echo $links; // show page numbers after the results list again if you feel like it.
Pingback: PaperMashup.com: Easy PHP Pagination | Webs Developer
You can easily do this in ASP.NET MVC!
You can better use SQL_CALC_FOUND_ROWS so you dont have to create two querys that are doing the same.
Nice! ( though I’am not a big fan of all the if-else nesting going on)
Spice it up with a little bit more of code-commenting
Could you upload the data you used for the database? It would be really useful
PHP4? Why?
Excellent Post,
Perfectly working…..Need this kinds of post to help us…
Regards
Limno.
Nice.
This is similar to http://www.phpeasystep.com/phptu/29.html
Pingback: uberVU - social comments
Top man! Thanks for sharing.
This is possibly one of the cleaner examples around on the internet to date.
No doubt it will help a fair few.
Cheers!
Dan.
Designer and web developer, Co-founder and Technical Director at Harkable.com London. Previously I worked at InMobi, Spotify and MySpace. Interests include photography and making short videos. Also an avid F1 fan.
Follow us on Twitter and get in-stream updates.
Subscribe to all the Papermashup tutorials and articles straight to your RSS reader.
Sign up and get all the Papermashup tutorials straight to your inbox.
69 discussions around Easy PHP Pagination