Pagination

Example PaginationPagination refers to splitting up a large result set into multiple pages. Probably the most recognized use of pagination is that displayed by Google when you perform a search. As long as there have been applications, there has been a need to paginate. Everything from long documents to search results, it's something almost every app you use has in common. Considering just how common pagination is, it's the one thing that seems to trip up many amateur programmers. Today I'm going to go over how to create a simple pagination feature in PHP with data collected from a MySQL database. You can download the sources and example database at the end of the post.

The Basics

Let's start with just displaying the content on the screen in a table. Throughout this post I am going to be using a table called 'users' with fields for an ID, a first name, last name and email address. Here's some basic code that will just output these details into a (very long) table:

  1. <?php
  2.     $res = mysql_query("
  3.         SELECT *
  4.         FROM users
  5.     ");
  6. ?>
  7. <table cellspacing="1" cellpadding="0" width="100%">
  8.     <thead>
  9.         <th>ID</th>
  10.         <th>First Name</th>
  11.         <th>Last Name</th>
  12.         <th>Email</th>
  13.     </thead>
  14.     <tbody>
  15.         <?php while ($user = mysql_fetch_assoc($res)): ?>
  16.             <tr>
  17.                 <td><?php echo $user['id']; ?></td>
  18.                 <td><?php echo $user['first']; ?></td>
  19.                 <td><?php echo $user['last']; ?></td>
  20.                 <td><?php echo $user['email']; ?></td>
  21.             </tr>
  22.         <?php endwhile; ?>
  23.     </tbody>
  24. </table>

Screenshot a table listing This is a pretty simple piece of code. We run a MySQL query to fetch all the users in the system -- we've all done that before, right? Of course the problem is when there are just too many users to list all at once. In the case of my example database, there are 200 records.

Introducing: LIMIT

A feature of any SQL database (that follows standards, anyway) is the ability to tell the server where to start returning rows from, and how many rows to return. Let's first modify the query a bit so it looks like this:

  1. $res = mysql_query("
  2.     SELECT *
  3.     FROM users
  4.     LIMIT 5
  5. ");

The LIMIT 5 makes the database return a maximum of 5 rows. So instead of returning all 200 of the rows in my example database, only the first 5 are returned -- that would be users with ID's 1-5.

In addition to just limiting the number of rows to return, you can also provide an offset. The offset is how many rows to skip before returning the result set. For example, let's modify the query one more time:

  1. $res = mysql_query("
  2.     SELECT *
  3.     FROM users
  4.     LIMIT 10, 5
  5. ");

The first number is the offset, and the second number is the row count. LIMIT 10, 5 means "Get 5 rows starting after the 10th row". In other words, rows 11-15.

So the magic behind pagination is this LIMIT clause. The rest of the work is just some basic PHP to display a page selector, and a bit of math to get the offset and row count from the page number.

The PHP Side Of Things...

Before we start, let's outline what information we need available:

The only "hard parts" are getting the number of total rows, calculating how many pages are required to show them all, and calculating the offset for use in the LIMIT clause. Here's how I did it:

  1. $per_page = 10;
  2. $cur_page = isset($_REQUEST['p']) ? (int)$_REQUEST['p'] : 1;
  3.  
  4. $res = mysql_query("
  5.     SELECT COUNT(*)
  6.     FROM users
  7. ");
  8. $num_rows = mysql_result($res, 0, 0);
  9.  
  10. $total_pages = ceil($num_rows / $per_page);
  11.  
  12. if ($cur_page <1 || $cur_page> $total_pages) {
  13.     $cur_page = 1;
  14. }
  15.  
  16. $offset = (($cur_page - 1) * $per_page);

Now that we have the code, let's go over it:

Now that we have the numbers, we can alter our data-getting query and plug them into the LIMIT clause:

  1. $res = mysql_query("
  2.     SELECT *
  3.     FROM users
  4.     LIMIT $offset, $per_page
  5. ");

Tada! We're all done! Well, that part at least. The only part left is to generate the links to the other pages.

Generating The Page Links

There are several different styles of page links. I prefer the kind that have a first/last and prev/next links to the side of the actual page links, and the current page should be surrounded by 5 pages to the left/right. For example, if I'm on page 15, there will be links to pages 9-14 on the left and pages 16-20 on the right. This is the style that I'm going to demonstrate here.

Undoubtedly there are numerous ways to generate such a navigation. Here's how I did it:

  1. <?php
  2.     $page_pad = 5;
  3.    
  4.     $min_page = max(1, $cur_page - $page_pad);
  5.     $max_page = min($total_pages, $cur_page + $page_pad);
  6.    
  7.     $show_prev = $cur_page> 1 ? $cur_page - 1 : false;
  8.     $show_next = $cur_page <$total_pages ? $cur_page + 1 : false;
  9. ?>
  10. <div class="page_nav">
  11.     <ul>
  12.         <li><a href="?p=1">&laquo; First</a></li>
  13.         <?php if ($show_prev): ?><li><a href="?p=<?php echo $show_prev; ?>">&lt;Prev</a></li><?php endif; ?>
  14.        
  15.         <?php for ($page = $min_page; $page <= $max_page; $page++): ?>
  16.         <li <?php if ($page == $cur_page): ?>class="cur_page"<?php endif; ?>><a href="?p=<?php echo $page; ?>"><?php echo $page; ?></a></li>
  17.         <?php endfor; ?>
  18.        
  19.         <?php if ($show_next): ?><li><a href="?p=<?php echo $show_next; ?>">Next&gt;</a></li><?php endif; ?>
  20.         <li><a href="?p=<?php echo $total_pages; ?>">Last &raquo;</a></li>
  21.     </ul>
  22. </div>

There you have it! Pretty simple, isn't it?

Conclusion

I hope I've helped some new programmer out there with this post. I had just gotten tired of so many people asking me how to add pagination to their apps and not having any definitive source to point them to. Not exactly the most advanced stuff, but still something I though needed to be covered.

You can download the full source code here. The package contains a PHP file, a CSS file and an SQL file that contains the test 'users' table and its data. The result looks like this:

Screenshot of pagination in action

Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically each day to your feed reader.

Trackbacks & Pingbacks

No trackbacks/pingbacks yet.

Comments

Another nice little tutorial. I tend to pass the offset value in the query string rather than the page number, but it makes little difference. It simply allows you to manipulate your results a bit more.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(required)

(required)