PHP and MySQL Pagination

I was reading my daily subscription of phpclasses.org the other day when I saw a class called “Paginazione”,
by Stefano V., an Italian web designer, “another pagination class” I thought and so I moved on to my Google Reader page where in one of the posts I saw the exact same class again and the author of this post was talking about how good of a class this was so I decided to check it out. The comments were in Italian but the code was neat so it did not matter.

In fact this class is really good. I have seen many PHP&MySQL pagination classes but most are not flexible, Stefano’s class on the other hand seems to have been developed for WordPress blogs since the query in the example file is “SELECT * FROM wp_posts”, but we will modify it for any page as you will see. The constructur in this class takes only 3 paramters, the query, number of results to show, and the variable where the page number will be stored. The class is made up of only 3 functions, including the constructor, and it is only 120 lines long. All this, even the fact that it was made for WordPress, it' great because the code is like a framework to design your own pagination class.

So here we go.
The following code is Stefano's usage example.

<php
	require_once("libs/paginazione.inc.php");

	// classe di paginazione (query, numero di record per pagina, nome variabile di pagina da leggere)
	$pag = new Paginazione("SELECT * FROM wp_posts", 10, "pagina");

	// restituisce un array multi-dimensionale con i record
	if($record = $pag->Show())
	{
		foreach($record as $row)
		{
			echo $row['ID'] . "<br />";
		}
	}
	else
	{
		echo "Nessun Record Trovato!";
	}

	// restituisce i link alle pagine
	if($link = $pag->Link(3))
	{
		?>
		<a href="?pagina=<?=$link['first']?>">«</a> <?php
			foreach($link['before'] as $bf)
			{
				?><a href="?pagina=<?=$bf?>"><?=$bf?></a> <?php
			}
			?><?=$link['current']?> <?php
			foreach($link['after'] as $at)
			{
				?><a href="?pagina=<?=$at?>"><?=$at?></a> <?php
			}
		?><a href="?pagina=<?=$link['last']?>">»</a>
		<?php
	}

?>

This is the usage example you will end up with using the class I derived from the original.

   require_once("php/Pagination.php");
	// create a database object
   @ $db = new mysqli('localhost','username','password','databasename');
   // select records query
   $query="SELECT * FROM table";
   // how many do you want to show
   $show=2;
   // GET variable for page
   $variable="p";
   // create Paginazione object
   $Pag = new Paginazione($query, $show, $variable,$db);

    if($record = $Pag->Show())
    {
        foreach($record as $row)
        {
		  // show the records: This is where you make your links using the rows in your database
		  // rows are associative
            echo "<p><a href=\"#\">".$row['rowname'] . "</a></p>";
        }
    }
    else
    {
		// message if there are no records
        echo 'Sorry, No Records Found';
    }

    // Navigation
	$moreParams="category=1&section=2";
	$Pag->navigation($moreParams);

One of the first things I had to do was add a MySQL connection, the connection is using the object oriented way of connecting which also involved changing some lines in the class not only the example above.

Like I mentioned previously, some pagination classes require heavy modification before you can get it to work with your own code, so in trying to remake this class I tried to add variables to increase flexibility as much as possible. In order for you to make the class work with your website you are going to have to set the following variables.

Mobile Development Tutorials

		//errors
		//if the class cannot connect to the database say...
		private $cantConnectToDB="Sorry, could not connect to database";
		// link buttons: The text you will see in the First, Previous, Next, and Last buttons
		private $firstLink="First";
		private $backLink="< prev";
		private $nextLink="next >";
		private $lastLink="Last";
		// HTML attributes for buttons: set the CSS properties for each of the buttons
			// enabled buttons
			private $enabledButton='class="enabled"';
			// disabled buttons
			private $disabledButton='class="disabled"';
			// current number
			private $currentButton='class="current"';

Important: The navigation menu is inside a div with a class called "pagination" in the "Navigation" function, remember to change the value if yours is different.

As you can tell from the previous usage examples, the original class did not have a “Navigation” function, you had to make the navigation menu yourself using the returned array from the function Link. But what if you wanted the save navigation in different pages? to do this I added a function called “Navigation” and although not necessary, I changed the “Link” function from public to private. So if you do want to make your own navigation menu from the returned array, simply change the Link function back to public.

// This is the new function: it can take other parameters like I show
// in my usage example.
		public function navigation($otherParams)
		{
			if($link = $this->Link(3))
			{
			echo "<div class=\"pagination\">"; // pagination begins
				if($this->link['back'])
				{
		echo"
       <a {$this->enabledButton} href=\"?{$this->varq}={$link['first']}&{$otherParams}\">{$this->firstLink}</a>
       <a {$this->enabledButton} href=\"?{$this->varq}={$link['back']}&{$otherParams}\">{$this->backLink}</a>";
				}
				else
				{
			echo"

	<a {$this->disabledButton} href=\"#\">{$this->firstLink}</a>
	<a {$this->disabledButton} href=\"#\">{$this->backLink}</a>";
				}

            foreach($link['before'] as $bf)
				{
                echo"<a href=\"?{$this->varq}={$bf}&{$otherParams}\">{$bf}</a>";
				}

            echo "<a {$this->currentButton}>".$link['current'].'</a>';

            foreach($link['after'] as $at)
				{
                echo"<a href=\"?{$this->varq}={$at}&{$otherParams}\">{$at}</a>";
				}
			if($this->link['next']<=$this->link['last'])
				{
        echo"
		<a {$this->enabledButton} href=\"?{$this->varq}={$link['next']}&{$otherParams}\">{$this->nextLink}</a>
		<a  {$this->enabledButton} href=\"?{$this->varq}={$link['last']}&{$otherParams}\">{$this->lastLink}</a>";
		}
			else
				{
        echo"
		<a {$this->disabledButton} href=\"#\">{$this->nextLink}</a>
		<a  {$this->disabledButton} href=\"#\">{$this->lastLink}</a>";
		}
		echo '</div>';//Pagination ends
			}
		}

As you can see if you prefer to use the “ul” tag this can easly be changed by replacing “div” with “ul” and adding “li” infront and after every anchor tag.

This is the resulting class.


	class Paginazione
	{
		private $xpage = 0;
		private $tot = 0;
		private $varq = "";
		private $totpag = 0;
		private $cpage = 0;
		private $SQL = "";
		private $record = array();
		//errors
		private $cantConnectToDB="Sorry, could not connect to database";
		// link buttons
		private $firstLink="First";
		private $backLink="< prev";
		private $nextLink="next >";
		private $lastLink="Last";
		// HTML attributes for buttons
		private $enabledButton='class="enabled"';
		private $disabledButton='class="disabled"';
		private $currentButton='class="current"';

		public function Paginazione($SQL, $xpage, $varq,&$db)
		{
			// le rendo globali
			$this->xpage = $xpage;
			$this->varq = $varq;
			$this->SQL = trim($SQL);
			$this->dbObject=$db;

			if (mysqli_connect_errno())
			{
				echo $this->cantConnectToDB;
				exit;
			}
			// pagina corrente sia get che post
			$this->cpage = (isset($_REQUEST[$varq])) ? (int)$_REQUEST[$varq] : 1;

			// inizio record
			$inizio = $xpage * ($this->cpage - 1);

			$ct = $this->dbObject->query($this->SQL);

			// record totali
			$this->tot = $ct->num_rows;

			// se ci sono record
			if($this->tot > 0)
			{
				// pagine totali
				$this->totpag = ceil($this->tot / $xpage);

				// scrivo ed eseguo la query mirata
				$target = " LIMIT " . $inizio . ", " . $xpage;
				//
				$ex = $this->dbObject->query($this->SQL . $target);

				while($ft = $ex->fetch_assoc())
				{
					$record[] = $ft;
				}

				$this->record = $record;
			}
			else
			{
				$this->record = array();
			}
		}

		public function Show()
		{
			if(count($this->record) > 0)
			{
				return $this->record;
			}
			else
			{
				return false;
			}

		}

		private function Link($nlink=4)
		{
			$before = array();
			$after = array();

			if($this->cpage < $nlink)
			{
				$nlink *= 2;
				$nlink -= ($this->cpage - 1);
			}
			elseif($this->cpage > ($this->totpag - $nlink))
			{
				$nlink *= 2;
				$nlink -= ($this->totpag - $this->cpage);
			}

			for($i = $nlink; $i>=1; $i--)
			{
				if(($this->cpage - $i) >= 1)
				{
					$before[] = $this->cpage - $i;
				}
			}

			for($i = 1; $i<=$nlink; $i++)
			{
				if(($this->cpage + $i) <= $this->totpag)
				{
					$after[] = $this->cpage + $i;
				}

				if($this->cpage == $nlink)
					$nlink += 1;
			}

			$this->link["first"] = 1;
			$this->link["before"] = $before;
			$this->link["current"] = $this->cpage;
			$this->link["after"] = $after;
			$this->link["last"] = $this->totpag;

			$this->link['back']=$this->link['current']-1;
			$this->link['next']=$this->link['current']+1;

			if($this->cpage <= $this->totpag && $this->totpag > 1)
			{
				return $this->link;
			}
			else
			{
				return false;
			}
		}

		public function navigation($otherParams)
		{
			if($link = $this->Link(3))
			{
			echo "<div class=\"pagination\">"; // pagination begins
				if($this->link['back'])
				{
		echo"
       <a {$this->enabledButton} href=\"?{$this->varq}={$link['first']}&{$otherParams}\">{$this->firstLink}</a>
       <a {$this->enabledButton} href=\"?{$this->varq}={$link['back']}&{$otherParams}\">{$this->backLink}</a>";
				}
				else
				{
			echo"

	<a {$this->disabledButton} href=\"#\">{$this->firstLink}</a>
	<a {$this->disabledButton} href=\"#\">{$this->backLink}</a>";
				}

            foreach($link['before'] as $bf)
				{
                echo"<a href=\"?{$this->varq}={$bf}&{$otherParams}\">{$bf}</a>";
				}

            echo "<a {$this->currentButton}>".$link['current'].'</a>';

            foreach($link['after'] as $at)
				{
                echo"<a href=\"?{$this->varq}={$at}&{$otherParams}\">{$at}</a>";
				}
			if($this->link['next']<=$this->link['last'])
				{
        echo"
		<a {$this->enabledButton} href=\"?{$this->varq}={$link['next']}&{$otherParams}\">{$this->nextLink}</a>
		<a  {$this->enabledButton} href=\"?{$this->varq}={$link['last']}&{$otherParams}\">{$this->lastLink}</a>";
		}
			else
				{
        echo"
		<a {$this->disabledButton} href=\"#\">{$this->nextLink}</a>
		<a  {$this->disabledButton} href=\"#\">{$this->lastLink}</a>";
		}
		echo '</div>';//Pagination ends
			}
		}
	}

I cannot provide you the original class because by doing so I would be “stealing” downloads from Stefano who gets points from phpclasses.org whenever someone downloads his class, but I will give you the link to the class so you can get it from there if you want to compare it or build your own.Link to the original “Classe Paginazione” (Pagination Class)

blog comments powered by Disqus