MVC Pagination

Hey guys,

I am having some trouble with the design/flow for pagination in an MVC framework.

I have access to all my data/rows in the controller, but I need to know how to pass this to the view so that it can properly generate pages, etc.

Should I pass the row_subset, total_rows, curr_page, and rows_per_page to my view? Seems a bit like overkill…

Or perhaps I should build a pagination class that I pass to my views ie (class PagableSet)

Any help appreciated.

Yes, you have to pass this to the view anyway.
First variant is to call your view like:
$template->render(‘view_name’, array(‘rowsCount’ => $rowsCount, ‘itempsPerPage’ => $ipp, ‘curPage’ => $page));
Second variant is to create properties for all that data and pass only reference to the calling controller to the view.

First is PUSH, second is PULL approach. But you have to do it anyway.

Hey thanks. Yeah, I decided to put all that information into a pagination class and pass it onto my view. The code is below if anyone is interested.


<?
	// IN CONTROLLER
	$dataSet = array(1,2,3,4,5,6,7,8,9,10);

	$currPage = ($_GET["pg"])?$_GET["pg"]:1;
	
	$pagination = new Pagination(sizeof($dataSet), 2, $currPage);

	// IN VIEW
	
	// Use default styling/automatic generation
	echo $pagination->getLinksHtml("http://localhost/paginationtest.php", "pg");

	// custom styling
	for($i=1; $i<=$pagination->getNumPages(); $i++) {
		//etc etc
	}
?>

<?
class Pagination
{
	private $totalItems;
	private $itemsPerPage;
	private $currPage;

	public function __construct($totalItems, $itemsPerPage, $currPage)
	{
		$this->totalItems = $totalItems;
		$this->itemsPerPage = $itemsPerPage;
		$this->currPage = $currPage;
	}

	public function getLinksHtml($baseUrl, $pageVar)
	{
		$html = "";

		if ($this->hasPrev()) {
			$html .= '<a href="'.$baseUrl.'?'.$pageVar.'='.($this->currPage-1).'">';
			$html .= 'Previous';
			$html .= '</a> ';
		}

		for($i=1; $i<=$this->getNumPages(); $i++) {
			if ($i != $this->currPage) {
				$html .= ' <a href="'.$baseUrl.'?'.$pageVar.'='.$i.'">'.$i.'</a> ';
			} else {
				$html .= ' '.$i.' ';
			}
		}

		if ($this->hasNext()) {
			$html .= ' <a href="'.$baseUrl.'?'.$pageVar.'='.($this->currPage+1).'">';
			$html .= 'Next';
			$html .= '</a>';
		}

		return $html;
	}

	public function hasPrev()
	{
		if ($this->currPage > 1) {
			return true;
		} else {
			return false;
		}
	}

	public function hasNext()
	{
		

		if ($this->currPage < $this->getNumPages()) {
			return true;
		} else {
			return false;
		}
	}

	public function getNumPages()
	{
		$numPages = ceil($this->totalItems/$this->itemsPerPage);

		return $numPages;
	}	
}
?>


Maybe you could take a look at Zend_Paginator: http://framework.zend.com/manual/en/zend.paginator.html

You could get some ideas about how to implement something similar in your MVC.

The thing I like about the Zend_Paginator is that you are passing just a select object to it - and the paginator itself modifies the select query based on request parameters. Nice approach.

Create a class that calculates the correct limit and offset based on the page. Pagination is a just a number game based on the total amount of records, records per page and current page. It deserves a separate class. Then you can even place some display logic in that class to build pagination dropdowns, navs and/or the dropdown javascript if you hate repeating all that stuff as well. You could even make it a separate class that requires a pagination object.

controller


$pagination = new Pagination(10,1200,3);
$offset = $pagination->getOffset();
$limit = $pagination->getLimit();

view


$pages = $pagination->getPages();
$page = $pagination->getPage();
$total = $pagination->getTotal();
$pagination->makeMenu();