SELECT field1, field2, ...
FROM table
WHERE condition
LIMIT StartRow, TotalRows
SELECT COUNT(*) FROM table WHERE condition
This will work but MySQL provides another way for us to do this using the
SQL_CALC_FOUND_ROWS.
SELECT SQL_CALC_FOUND_ROWS, field1, field2, ...
FROM table
WHERE condition
LIMIT 20,10
Followed by
SELECT FOUND_ROWS()
Putting it all together
CREATE TABLE `client` (
`id` int(11) NOT NULL auto_increment,
`firstname` varchar(50) default NULL,
`surname` varchar(50) default NULL,
`email` varchar(50) default NULL,
PRIMARY KEY (`id`)
)
The code makes use of two classes
// Our connection variables - in a real project these would most likely be
// included in a config file that would be included in the application
// deprecating the requirement to include them here.
// They are reproduced here for clarity.
define('db_server','localhost');
define('db_user','user');
define('db_password','password');
define('db_database','ee');
class Database
{
private $connection; // A property to hold our database connection
function __construct()
{
$this->connection = new mysqli(
db_server,
db_user,
db_password,
db_database);
}
// A static method to return the current database connection
// The function ensures a single instance of the database
// object is used in the application
static function &getConnection()
{
static $connection;
// If a database object has not been instantiated then do so
if (!is_object($connection)) {
$connection = new Database();
}
return $connection;
}
// Wrapper function for the query method
// This can be expanded with additional parameters to
// use prepared statements etc
function query($query)
{
return $this->connection->query($query);
}
}
The
Result class manages the results we retrieve from the database and renders the client table and pagination
// The pg_pagesize constant determines how many results you want
// to see on a page. Again, this could be defined in the config file.
// In more advanced implementations this can be modifiable by the
// reader to show more or less items on a page.
define('pg_pagesize', 10);
class Results
{
private $pagenumber = null; // Requested page number
private $result = null; // Results from querying the client table
private $db = null; // Instance of the Database singleton class
private $total = 0; // Total number of records in the client table
// The constructor takes a requested pagenumber
// It builds and executes the query against the client's table
// It also calculates total number of rows in the client's table
function __construct($pagenumber)
{
// We want to work with pagenumbers starting from 0 - but humans
// are used to page numbers starting from 1 so we need to compensate.
$this->pagenumber = $pagenumber - 1;
// Store the pagenumber in the session so we don't annoy users
// who navigate away from the page and want to see the same
// results when they return
$_SESSION['pagenumber'] = $this->pagenumber;
// Calculate the start row
$start = pg_pagesize * $this->pagenumber;
// Build the query to fetch the required rows from the database
// starting from the requested page
$this->db = Database::getConnection();
$query = sprintf("SELECT SQL_CALC_FOUND_ROWS * FROM `client` LIMIT %d, %d",
$start, pg_pagesize);
$this->result = $this->db->query($query);
// Fetch the calculated total rows of the dataset without the LIMIT
$total = $this->db->query("SELECT FOUND_ROWS() AS total");
$row = $total->fetch_object();
$this->total = $row->total;
}
// This is the workhorse of the class. It cycles through the dataset
// and outputs the HTML rows for our data table
function showResults()
{
print "<table>" . _L;
print "\t<tr>" . _L;
print "\t\t<th>First Name</th><th>Surname</th><th>Email</th>" . _L;
print "\t</tr>" . _L;
while($row = $this->result->fetch_object()) {
print "\t\t<tr>" . _L;
printf("\t\t\t<td>%s</td><td>%s</td><td>%s</td>" . _L,
$row->firstname, $row->surname, $row->email);
print "\t\t</tr>" . _L;
}
print "</table>" . _L;
$this->result->close();
}
// Here is where the pagination happens.
// The class is designed that this function can be called from
// anywhere in the code (and multiple times)
// It is not dependent on showResults having already been called.
function showPagination()
{
// Calculate how many pages there are. We do that by taking the
// integer division of the total rows
$pages = intval($this->total / pg_pagesize);
// and adding 1 if there is a reminder.
$pages += ($this->total%$pages)?1:0;
// Finally we have enough information to output our pagination HTML
print "<div class=\"page-navigation\">" . _L;
print '<a href="client.php?page=1" class="pagination-arrows"><<</a>';
// We don't want to show the goto previous record if we are on record 1
if ($this->pagenumber > 0) {
printf( "<a href=\"client.php?page=%d\" class=\"pagination-arrows\"><</a>",
$this->pagenumber);
}
for($i=1;$i<=$pages;$i++) {
if ($i == $this->pagenumber+1) {
printf("<span>%d</span>" . _L, $i);
}
else {
printf("<a href=\"client.php?page=%d\">%d</a>" . _L, $i, $i);
}
}
// We don't want to show goto next record if we are on the last page.
if ($this->pagenumber < $pages-1) {
printf("<a href=\"client.php?page=%d\" class=\"pagination-arrows\">></a>",
$this->pagenumber + 2);
}
printf("<a href=\"client.php?page=%d\" class=\"pagination-arrows\">>></a>",
$pages);
print "</div>" . _L;
}
}
All that is left is to build the page that displays our results
// We are using sessions to store our pagenumber so initiate a session
session_start();
// shortcut to the newline character
define('_L', PHP_EOL);
// Include our workhorse files
require_once('database.php');
require_once('results.php');
// Work out what page number to use
// First we look to see if a page number is specified in the URL request.
// If it is we sanitize it to remove everything except numbers.
// If no page was found then default to the empty string
$pageno = isset($_GET['page'])
? preg_replace('/[^0-9]/', '', $_GET['page'])
: '';
// This could have been done on one line but has been split for clarity
// If pageno is empty then attempt to get it from the session.
// If the session is not set yet then default to 1.
$pageno = empty($pageno)
? (
isset($_SESSION['pagenumber'])
? $_SESSION['pagenumber'] + 1
: 1
)
: $pageno;
// Instantiate the results object to output to the page
$results = new Results($pageno);
?>
<!doctype html>
<html>
<head>
<title>Client Results Page</title>
</script>
<style type="text/css">
body {
font-size: 100%;
font-family: Arial;
}
table {
border-collapse: collapse;
font-size: 0.8em;
}
th, td {
border: 1px solid #888;
padding: 2px 5px;
}
tr:nth-child(2n) {
background: #effeff;
}
.page-navigation {
font-size: 0.6em;
}
.page-navigation a.pagination-arrows {
padding: 0 4px;
}
</style>
</head>
<body>
<?php
// Demonstrate that pagination can be output anywhere
// and any number of times
$results->showPagination();
// Display our results
$results->showResults(); ;?>
// Demonstrate that pagination can be output anywhere
// and any number of times
$results->showPagination();
?>
</body>
</html>
That's it - the basics of a pagination script that works with the MySQL functions
SQL_CALC_FOUND_ROWS and
FOUND_ROWS
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (4)
Commented:
Another one of the enduringly good examples of PHP pagination is this one from SitePoint.
http://www.sitepoint.com/perfect-php-pagination/
Author
Commented:http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
Commented:
<a href="http://www.credosystemz.com/training-in-chennai/best-php-training-in-chennai/">php training in chennai</a>
Commented:
- Thara,
Trainer @ Kamal Technologies, <a href="https://www.kamaltechnologies.in/php-sql-training/">Best PHP - SQL Training institute in Chennai</a>