How to script a pagination class
This class makes it possible to list a number of items on several pages. It comes with a navigation of a set of links, and you also have the option to define how much span that navigation should have.
Hello!
This is a basic pagination class, coded in PHP.
So let's get started!
The first thing we have to do, is telling PHP that we want to create a class.
PHP Code:
class pagination {
// This is where our class content will be.
}
So, what could be good names for variables, and how many do we need?
Well, since this pagination class should work in all ways, and not just with a mysql database, we cannot use any mysql queries inside the class. That will be done outside of the class. The class main function is just to calculate how many pages, and return those in an array.
INT: $totalPages - This is the total amount of pages. This is based on how many results per page, and how many results.
INT: $totalResults - This is the total amount of results.
INT: $totalPerPage - This is how many results per page we want. This is set before you calculate how many pages.
INT: $currentPage - The value of the current page that the user is viewing.
INT: $firstResult - The value of the first result on the current page. This is calculated within the class.
So, that's the variables I want to use for this. It's quite simple, it's not alot of variables, and they're pretty easy to understand what they do.
Next thing we need to do, is to figure out what functions we need.- 1 function to set $totalPerPage
- 1 function to set the value of $currentPage
- 1 function to calculate how many pages, and return those
- 1 function to check if a pagenumber exists within the array of pages. This is used for next and previous links.
- And 1 function to get the value of $currentPage and $totalPages in an array.
PHP Code:
class pagination {
// The total values.
private $totalPages;
private $totalResults;
private $totalPerPage;
// The current values.
private $currentPage;
// The first result on current page.
private $firstResult;
/**
* Sets the maximum allowed results per page
*
* @param integer $max, default 10
**/
public function setMax($max = 10) {
}
/**
* Generate the first result on the current page
*
* @param integer $page, which page we're currently viewing
* @return integer first result
**/
public function setPage($page) {
}
/**
* Generates how many pages based on the total amount of results
*
* @param array $results, an array of all the results
* @return array of pages
**/
public function getPages($results) {
}
/**
* Checks if a link is valid
*
* @param integer $pagenr, the number of the page you want to check if it exist
* @return true or false
**/
public function checkLink($pagenr) {
}
/**
* Generate the current page number
*
* @return array, [0] = the current page, [1] = total pages
**/
public function getCurrentPage() {
}
}
So, those are our functions. As you see, all the variables are private. This is done for added security, because the only way now to access a value of one of the variables, is by calling them INSIDE the class.
PHP Tip: Always use private for variables in classes, unless you REALLY need them to be public.
Let's take a look at the first function. It's a really basic function, because it's just supposed to assign a value to a variable. However, this value needs to be an integer, thus:
PHP Code:
public function setMax($max = 10) {
if(is_numeric($max)) {
$this->totalPerPage = $max;
}
}
$max is a value that's used when calling the function.
We simply check if it's numerical(integer), and if it is, we asign the value of $max, to the variable private $totalPerPage.
Still with me? I hope so, because now we'll do some math(yaay!...).
PHP Code:
public function setPage($page) {
if(is_numeric($page)) {
$this->currentPage = mysql_real_escape_string($page);
$this->firstResult = (($this->currentPage * $this->totalPerPage) - $this->totalPerPage);
return $this->firstResult;
}
}
Same here, we use $page as a variable when calling the function. This value will ofcourse be the value of the current page(for example 2 = we're looking on page 2).
We check if it's an integer because we're not allowing anything else to be passed, and if it is, we assign the value of $page, to private $currentPage.
After that, the fun begins... or not, depending if you enjoy math.
Some way, we need to calculate the number of the first result on THAT page. So we need to take into consideration how many results we are allowing per page, and also what the current page is.
PHP Code:
$this->firstResult = (($this->currentPage * $this->totalPerPage) - $this->totalPerPage);
Let's just play with the thought that you're viewing page 3, and you've set the configuration so it's displaying 10 results per page.
Then it would be like: 3 * 10, which is 30. But that's just the amount of result you've viewed after reading whole page 3, and we want the first result, so we need to subtract it by the amount of results you've allowed it to display PER PAGE, leaving us with:
(3*10) - 10 = 20
Not really hard, but took some time to figure out.
After that, we return the value of the private $firstResult. If we didn't, we would need to create another function just to get that value, since the variable is private and you cannot get it in any other way.
PHP Code:
public function getPages($results) {
$this->totalResults = count($results);
$totalPages = $this->totalResults / $this->totalPerPage;
$this->totalPages = ceil($totalPages);
$x = 1;
$array = array();
while($x <= $this->totalPages) {
$array[] = $x;
$x++;
}
return $array;
}
This function is quite big. The biggest function in this class actually.
The first thing we do here, is to count the amount of results, and assigning that value to private $totalResults.
After that, we calculate how many pages we get out of those results, based on the value of private $totalPerPage.
Again, I'm going to use my previous example.
30 results, and 10 results per page: 30 / 10 = 3 pages. This is basic math.
After that we ceil it, and what that does, is to round it up. Because what if when we divide, it gives us 7,43 pages, we don't want that, now do we?
So we round that up to 8, and that's what the ceil function do.
Since private $totalPages is just an integer, and I want it to be an array, I'm creating an array inside this function that will be used only in this function and then returned.
I assign the value of 1 to the variable $x, and I create an array of the variable $array.
Then I use a while loop.
while $x is less or equal to private $totalPages, we do the things inside the bracket. And that is to assign the value of $x to a key inside the array $array, and after that we add 1 value to $x, and this is looped again and again until $x is higher than private $totalPages.
After that we return the array.
PHP Code:
public function checkLink($pagenr) {
if($pagenr <= $this->totalPages && $pagenr >= 1) {
return true;
}
return false;
}
This is really simple. We just check if the $pagenr is within page 1, and the private $totalPages.
If it is, we return true. If it's not, we return false.
PHP Code:
public function getCurrentPage() {
$array = array();
$array[] = $this->currentPage;
$array[] = $this->totalPages;
return $array;
}
Quite simple too. I'm just assigning the value of private $currentPage and private $totalPages to 2 different keys in an array.
Note that this array is also called $array, but it's NOT the same as the one in the getPages function.
PHP Tip: If you create a variable inside a function in a class, that variable is only set in THAT function and NEVER outside UNLESS you create that variable as a $this variable in the beginning of the class or make the variable global.
This is basicly the whole class. It's quite short, I know, but it certainly does the job!
Here's the whole script:
PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/
class pagination {
// The total values.
private $totalPages;
private $totalResults;
private $totalPerPage;
// The current values.
private $currentPage;
// The first result on current page.
private $firstResult;
/**
* Sets the maximum allowed results per page
*
* @param integer $max, default 10
**/
public function setMax($max = 10) {
if(is_numeric($max)) {
$this->totalPerPage = $max;
}
}
/**
* Generate the first result on the current page
*
* @param integer $page, which page we're currently viewing
* @return integer first result
**/
public function setPage($page) {
if(is_numeric($page)) {
$this->currentPage = mysql_real_escape_string($page);
$this->firstResult = (($this->currentPage * $this->totalPerPage) - $this->totalPerPage);
return $this->firstResult;
}
}
/**
* Generates how many pages based on the total amount of results
*
* @param array $results, an array of all the results
* @return array of pages
**/
public function getPages($results) {
$this->totalResults = count($results);
$totalPages = $this->totalResults / $this->totalPerPage;
$this->totalPages = ceil($totalPages);
$x = 1;
$array = array();
while($x <= $this->totalPages) {
$array[] = $x;
$x++;
}
return $array;
}
/**
* Checks if a link is valid
*
* @param integer $pagenr, the number of the page you want to check if it exist
* @return true or false
**/
public function checkLink($pagenr) {
if($pagenr <= $this->totalPages && $pagenr >= 1) {
return true;
}
return false;
}
/**
* Generate the current page number
*
* @return array, [0] = the current page, [1] = total pages
**/
public function getCurrentPage() {
$array = array();
$array[] = $this->currentPage;
$array[] = $this->totalPages;
return $array;
}
}
Examples:
So, how do you use this class you ask?
Well, here's 2 examples, 1 by me, and the 2nd one is by Salathe from talkphp.
Read the comments in the scripts for explanation.
MySQL example:
PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/
// Include the class file, get the page from $_GET, see if it's set, and if it isn't, assign it the value of 1.
// $max is used for setting the max number of results per page. $span is the value of the span.
include('pagination.php');
$p = $_GET['p'];
(isset($p)) ? $p : 1;
$max = 10;
$span = 3:
// Create the object and set some basic values.
$pagination = new pagination();
$pagination->setMax($max);
// Get the total results, and then calculate how many pages that becomes based on how many results per page.
$totSql = "SELECT * FROM `table`";
$totQuery = mysql_query($totSql) or die(mysql_error());
$totResults = mysql_fetch_array($totQuery);
$totPages = $pagination->getPages($totResults);
// Set the current page, and get the first result on it.
$first = $pagination->setPage($p);
// Get the results of the current page.
$exSql = "SELECT * FROM `table` LIMIT $first, $max";
$exQuery = mysql_query($exSql) or die(mysql_error());
$exResults = mysql_fetch_array($exQuery);
// Echo out the current page, and the total amount of pages.
$page = $pagination->getCurrentPage();
echo 'Page: '.$page[0].' of '.$page[1];
// If the current page minus the span is larger than 1, it means that the first page is outside the span, and thus we want to
// display it!
if(($page[0] - $span) > 1) {
echo '<a href="?page=1">First</a> ';
// If the current page minus (span + 1) is larger than 1, it means that the first page is outside the span AND it is outside the
// span with more than 1, and thus we want to add an extra ".." after the first link.
if(($page[0] - ($span + 1)) > 1) {
echo '.. ';
}
}
// Get previous page link, and check if it's valid.
$prevLink = $page[0] - 1;
if($pagination->checkLink($prevLink)) {
echo '<a href="?page='.$prevLink.'">Previous Page</a>';
}
// Here we echo out all the links based on what the span is set to.
foreach(range($page[0] - $span, $page[0] + $span) as $pageNumber) {
if($pageNumber < 1 OR $pageNumber > $page[1]) {
if($pageNumber == $page[0]) {
echo ' <strong><a href="?page='.$pageNumber.'>'.$pageNumber.'</a></strong> ';
}
else {
echo ' <a href="?page='.$pageNumber.'>'.$pageNumber.'</a> ';
}
}
}
// Get the next page link, and check if it's valid.
$nextLink = $page[0] + 1;
if($pagination->checkLink($nextLink)) {
echo '<a href="?page='.$nextLink.'">Next Page</a>';
}
// Same here as we did with the first link.
if(($page[0] + ($span + 1)) < $page[1]) {
echo ' .. ';
}
// Same here as we did with the first link.
if(($page[0] + $span) < $page[1]) {
echo ' <a href="?page='.$page[1].'">Last</a>';
}
foreach($exResults as $news) {
echo $news['news_title'];
echo '<br /><br />';
}
Image Gallery script, non-MySQL:
An example which uses a directory of images is given below. The folder structure is such that we have an images folder and within that a thumbs folder. Filenames match between the folders representing a thumbnail and full-sized version of the same image. It's up to you to create the thumbnails however you like.
PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Salathe
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/
include('pagination.php');
$p = (isset($_GET['p']) AND ctype_digit($_GET['p']) AND (int) $_GET['p'] > 0)
? (int) $_GET['p']
: 1;
$max = 10;
// Create the object and set some basic values.
$pagination = new pagination();
$pagination->setMax($max);
// Set up some directory variables
$dir = dirname(__FILE__).'/images/';
$webdir = 'images/';
$thdir = 'images/thumbs/';
// Grab all of the images
$images = glob($dir.'*.jpg');
// Set up pagination variables
$totPages = $pagination->getPages($images);
$first = $pagination->setPage($p);
$page = $pagination->getCurrentPage();
// Only select the portion of the images array
// that represents our page
$exResults = array_slice($images, $first, $max);
// Make links spaced a bit
echo '
<style type="text/css">
a { margin: 0 2px 0 0; }
</style>';
// Start pagination display
printf('Page: %d of %d | ', $page[0], $page[1]);
$pagination->checkLink($p - 1) AND printf('<a href="?p=%d">Previous Page</a>', $p - 1);
foreach ($totPages as $pageNumber) {
$tpl = ($pageNumber == $p)
? '<a href="?p=%1$d">%1$d</a>'
: '<a href="?p=%1$d"><strong>%1$d</strong></a>';
printf($tpl, $pageNumber);
}
$pagination->checkLink($p + 1) AND printf('<a href="?p=%d">Next Page</a>', $p + 1);
// Display current page of images
echo '<hr><div class="images">';
foreach($exResults as $image) {
$image = str_replace($dir, $webdir, $image);
$thumb = str_replace($webdir, $thdir, $image);
printf('<a href="%s" style="margin: 0 5px 5px 0;"><img src="%s" alt="%s"></a>',
$image, $thumb, basename($image));
}
echo '</div>';
So this is everything. I hope you learned something!