PHP howto - Database paging (pagination)
June 26th, 2008 Denham CooteOK, so it’s not quite the nuclear bomb I promised, but it’s just as much fun
Database paging, for those of you who are interested, is when you split the number of results returned by a query into smaller chunks, and then show those one page at a time. Think of how Google will display 10 results out of 4 236 735. Same thing.
The basic idea is to:
- Run your query, limited to the number of desired results
- Get the number of results that there would have been, without the limit
- Display the first set of results
- Build and display <prev> and <next> links, which, when clicked…
- Display the prev/next set of results, moved down/up by the desired amount
- Repeat 4 & 5
The following code sample is a very basic implementation of this idea. I have not checked the code, so apologies in advance if there are any bugs.
<?php $no_results = TRUE; // No results found yet $howmany = 10; // Return 10 results per query // Set default starting point of query to 0, or, if set, to $_GET['rs'] $row_start = (isset($_GET['rs'])) ? $_GET['rs'] : 0; // Do our SQL query, with something like LIMIT 0, 10 $sql = "SELECT SQL_CALC_FOUND_ROWS id, name, surname FROM person LIMIT ". $row_start .", ". $howmany .""; $result = mysql_query($sql); // Get the number of rows that would have been returned WITHOUT a limit clause, to be used later for paging. $count_sql = "SELECT FOUND_ROWS() AS total"; $count_sql_result = mysql_query($count_sql); $count_row = mysql_fetch_array($count_sql_result); $count_result = $count_row['total']; // Start looping through our result set while($row = mysql_fetch_array($result)) { $no_results = FALSE; // Save results of query to $line_output $line_output .= " <div class=\"someclassname\"> <div>". $row['id'] ."</div> <div>". $row['name'] ."</div> <div>". $row['surname'] ."</div> </div>"; } // Don't bother building paging if we don't have records if ($no_results) { $line_output = "No records found..."; $page_output = ""; } else { // Build <prev> and <next> links and save to $page_output $rs_prev = $row_start - $howmany; // where would prev page start, given current start less no. of records $rs_next = $row_start + $howmany; // where would next page start, given current start plus no. of records // If for some reason the next <prev> starting point is negative, do not display <prev> // This happens when our current starting point is already 0 // This may happen if some smartass manually changes the rs= bit in the url $page_output_prev = ($rs_prev < 0) ? "" : "<a href='?rs=".$rs_prev."'>Previous</a>"; // Will the next page jump start point exceed the number of records returned? // If so, don't display <next>' $page_output_next = ($rs_next >= $count_result) ? "" : "<a href='?rs=".$rs_next."'>Next</a>"; // Just something to put between <prev> & <next>, IF they are both active if (($page_output_prev == "") || ($page_output_next == "")) {$page_output_breaker = "";} else { $page_output_breaker = " || ";} // Build final paging output $page_output = $page_output_prev . $page_output_breaker . $page_output_next; } // Write the outputs echo $line_output; echo $page_output; ?>
A few points worth taking note of:
Row counting
To get the total number of results, I have used
SELECT SQL_CALC_FOUND_ROWS
followed by a second query
SELECT FOUND_ROWS() AS total
As stated in the comments, this will return the number of results that there would have been without a limit clause. There are other ways to achieve this, namely using count() in a second query, but this way is apparently quicker, and also slightly cleaner code.
Building the paging links
In the code I have used
$_GET['rs']
What this does is get the value from the part of the URL that looks something like http://www.yoursite.com/index.php?rs=10
That value then becomes our next starting point, and is injected into the SQL query.
I’ve seen some tutorials where page numbers are used instead of starting records. This is fairly easy to achieve, and involves dividing the number of records returned by the size of the desired result set to get the number of pages, and then multiply again when determining the next starting point for the limit. I’ve not done that in this tutorial for the sake of simplicity. Besides, Google uses the records, and not pages, method. Can’t be that terrible
Extending the functionality
In this example I’m echoing the result to screen. You could instead wrap this up in a function and return the results. Another easy modification would be to alternate the background colours, as shown in my previous howto.
And that’s it for today. If you found this useful, of would like to improve it, comments are always appreciated!



