OK, here is my latest code for the Pager following the back and forth with Tim. There are still some more additions I would like to make, but I think they might entail using Sessions -- so I need to think about a clean way to do that.
Code: Select all
class Pager {
var $datasource = null; // Pageable datasource object
var $page_size = 10; // number of rows of data per page
var $range_size = 10; // number of links in pager
var $current_page = 0;
var $first_page = 1;
var $last_page = -1;
var $first_row = 1;
var $last_row = 0;
var $start_row = 0;
var $end_row = 0;
var $page_param = 'page'; // parameter names for URLs
var $last_row_param = 'last_row';
var $page_size_param = 'page_size';
function Pager(&$datasource) {
$this->datasource = &$datasource;
}
function setPageSize($n) {
if ($n > 0) {
$this->page_size = $n;
}
}
function setRangeSize($n) {
if ($n > 2) {
$this->range_size = $n;
}
}
function setPageParameter($name) {
$this->page_param = $name;
}
function setPageSizeParameter($name) {
$this->page_size_param = $name;
}
function setLastRowParameter($name) {
$this->last_row_param = $name;
}
function setCurrentPage($n) {
if ($this->last_row < 0) { // do not access datasource if last_row has been set
$this->last_row = $this->datasource->getNumRows();
}
if ($this->last_row > 0) {
$this->last_page = ceil($this->last_row / $this->page_size);
if ($n < $this->first_page) {
$n = $this->first_page;
}
if ($n > $this->last_page) {
$n = $this->last_page;
}
$this->current_page = $n;
$this->start_row = ($n - 1) * $this->page_size + 1;
$this->end_row = $this->start_row + $this->page_size - 1;
if ($this->end_row > $this->last_row) {
$this->end_row = $this->last_row;
}
} else {
$this->last_page = 0;
$this->current_page = 0;
$this->start_row = 0;
$this->end_row = 0;
}
}
function getPageSize() {
return $this->page_size;
}
function getCurrentPage() {
return $this->current_page;
}
function getLastPage() {
return $this->last_page;
}
function getFirstPage() {
return $this->first_page;
}
function getFirstRow() {
return $this->first_row;
}
function getLastRow() {
return $this->last_row;
}
function getStartRow() {
return $this->start_row;
}
function getEndRow() {
return $this->end_row;
}
function getValues() {
return array(
'page_size' => $this->page_size,
'page_size' => $this->last_page,
'current_page' => $this->current_page,
'start_row' => $this->start_row,
'end_row' => $this->end_row,
'last_row' => $this->last_row,
);
}
function getRange() {
// get number of links each side of current page
$side_size = floor($this->range_size / 2);
$range_start = $this->current_page - $side_size;
$range_end = $range_start + $this->range_size - 1;
// bounds check lower side of range
if ($range_start < $this->first_page) {
$range_start = $this->first_page;
}
if ($range_end > $this->last_page) {
$range_end = $this->last_page;
}
return range($range_start, $range_end);
}
}
class PagerRequest {
var $pager = null;
function PagerRequest(&$pager) {
$this->pager = &$pager;
}
function process() {
$pager = &$this->pager;
if (isset($_GET[$pager->last_row_param])) {
$pager->current_page = intval($_GET[$pager->page_param]);
} else {
$pager->current_page = $pager->first_page;
}
if (isset($_GET[$pager->last_row_param])) {
$pager->last_row = intval($_GET[$pager->last_row_param]);
} else {
$pager->last_row = $pager->datasource->getNumRows();
}
if (isset($_GET[$pager->page_size_param])) {
$pager->page_size = intval($_GET[$pager->page_size_param]);
}
$pager->setCurrentPage($pager->current_page);
}
}
class PagerHTMLWriter {
var $pager = null;
var $no_current_link = true; // no link for current page
var $base_url = ''; // domain and script name part of URL
var $extra_params = array(); // array of parameters that are added to all URLs
function PagerHTMLWriter(&$pager) {
$this->pager = &$pager;
}
function getParameters($n=0) {
$params = $this->extra_params;
$params[$this->pager->last_row_param] = $this->pager->last_row;
$params[$this->pager->page_size_param] = $this->pager->page_size;
if ($n > 0) {
$params[$this->pager->page_param] = $n;
}
return $params;
}
function setExtraParameters($params=array()) {
$this->extra_params = $params;
}
function setBaseURL($url) {
$this->base_url = $url;
}
function getPageURL($n) {
if (($n > 0) && ($n <= $this->pager->last_page)) {
$params = $this->getParameters($n);
foreach ($params as $name => $value) {
$param_strs[$name] = $name . '=' . $value;
}
$url = $this->base_url . '?' . implode('&', $param_strs);
} else {
$url = '';
}
return $url;
}
function getPrevURL() {
if ($this->pager->current_page > $this->pager->first_page) {
$url = $this->getPageURL($this->pager->current_page - 1);
} else {
$url = '';
}
return $url;
}
function getNextURL() {
if ($this->pager->current_page < $this->pager->last_page) {
$url = $this->getPageURL($this->pager->current_page + 1);
} else {
$url = '';
}
return $url;
}
function getFirstURL() {
return $this->getPageURL($this->pager->first_page);
}
function getLastURL() {
return $this->getPageURL($this->pager->last_page);
}
function getRangeURLs() {
foreach ($this->pager->getRange() as $n) {
$urls[$n] = $this->getPageURL($n);
}
return $urls;
}
function getPageSizeURL($size) {
$save_page_size = $this->pager->page_size;
$save_no_current_link = $this->no_current_link;
$this->pager->page_size = $size;
$this->no_current_link = false;
$url = $this->getPageURL($this->pager->current_page);
$this->pager->page_size = $save_page_size;
$this->no_current_link = $save_no_current_link;
return $url;
}
function getPageLink($n, $text='', $attrs='') {
if (($n > 0) && ($n <= $this->pager->last_page)) {
$str = ($text ? $text : $n);
if ($this->no_current_link && ($n ==$this->pager->current_page)) {
$link = $str;
} else {
$link = '<a href="' . $this->getPageURL($n) . "\" $attrs>" . $str . '</a>';
}
} else {
$link = '';
}
return $link;
}
function getPrevLink($text='Prev', $attrs='') {
if ($this->pager->current_page > $this->pager->first_page) {
$url = $this->getPageLink($this->pager->current_page - 1, $text, $attrs);
} else {
$url = '';
}
return $url;
}
function getNextLink($text='Next', $attrs='') {
if ($this->pager->current_page < $this->pager->last_page) {
$url = $this->getPageLink($this->pager->current_page + 1, $text, $attrs);
} else {
$url = '';
}
return $url;
}
function getFirstLink($text='First', $attrs='') {
return $this->getPageLink($this->pager->first_page, $text, $attrs);
}
function getLastLink($text='Last', $attrs='') {
return $this->getPageLink($this->pager->last_page, $text, $attrs);
}
function getRangeLinks($attrs='') {
foreach ($this->pager->getRange() as $n) {
$links[$n] = $this->getPageLink($n, '', $attrs);
}
return $links;
}
function getPageSizeLink($size, $text='', $attrs='') {
if ($size > 0) {
$str = ($text ? $text : $size);
$link = '<a href="' . $this->getPageSizeURL($size) . "\" $attrs>" . $str . '</a>';
} else {
$link = '';
}
return $link;
}
}
And here is an example using it:
Code: Select all
include 'Pager.php';
include 'PageableArray.php';
// initialize an array for testing
for ($i=43; $i<=75; ++$i) {
$myarray[$i] = 'This is row ' . $i;
}
// create a data object that has the interface needed by the Pager object
$datasource = & new PageableArray($myarray);
if ($datasource->getNumRows() > 0) {
// create pager using values from datasource and request params
$pager = & new Pager($datasource);
$pager->setRangeSize(5);
// create a request processor to set pager from GET parameters
$request = & new PagerRequest($pager);
$request->process();
// create a HTML writer to output
$writer = & new PagerHTMLWriter($pager);
// get rows of data
$start_row = $pager->getStartRow();
$end_row = $pager->getEndRow();
$rows = $datasource->getRows($start_row, $end_row);
// display the data
echo '<table border="1">';
$n = $start_row;
foreach ($rows as $value) {
echo '<tr>';
echo '<td>' . $n++ . '.</td><td>' . $value . '</td>';
echo '</tr>';
}
echo '</table>';
// display the paging links
echo $writer->getPrevLink() . ' | ' . implode(' | ', $writer->getRangeLinks()) . ' | ' . $writer->getNextLink() . '<p/>';
} else {
echo 'No records found.';
}
If you want to add a second Pager to a page like Tim showed, you would add something like this:
Code: Select all
// configure first pager here
$pager2 = & new Pager($datasource);
$pager2->setPageParameter('page2');
$pager2->setPageSizeParameter('page_size2');
$pager2->setLastRowParameter('last_row2');
$request->PagerRequest($pager2);
$request->process();
$writer2 = & new PagerHTMLWriter($pager2);
$start_row2 = $pager2->getStartRow();
$end_row2 = $pager2->getEndRow();
// these two lines copy each pager's parameters to the other pager as extra parameters
$writer->setExtraParameters($writer2->getParameters($pager2->getCurrentPage()));
$writer2->setExtraParameters($writer->getParameters($pager->getCurrentPage()));
// show first pager here
$rows = $datasource->getRows($start_row2, $end_row2);
$n = $start_row2;
#echo '<pre>' . print_r($rows, 1) . '</pre>';
echo '<table border="1">';
foreach ($rows as $value) {
echo '<tr>';
echo '<td>' . $n++ . '.</td><td>' . $value . '</td>';
echo '</tr>';
}
echo '</table>';
echo $writer2->getPrevLink() . ' | ' . implode(' | ', $writer2->getRangeLinks()) . ' | ' . $writer2->getNextLink() . '<p/>';
And here is my PagableArray class with a check for no data added:
Code: Select all
class PageableArray {
var $data;
function PageableArray($data) {
$this->data = $data;
}
function getNumRows() {
return count($this->data);
}
function getRows($begin, $end) {
if (count($this->data) > 0) {
--$begin;
return array_slice($this->data, $begin, $end - $begin);
}
}
}