Code: Select all
/*
CLASS Indexer
The simple arithmetic required for pagination-type operations.
A (modified) iterator would seek to the getOffset() value.
isValid() would be called per iteration.
*/
class Indexer
{
var $i = 0;
/*
param (integer) $total_rows
param (integer) $subset_size ie max rows per page
*/
function Indexer($total_rows, $subset_size)
{
$this->total_rows = $total_rows;
$this->subset_size = $subset_size;
}
/*
param (integer)
return (integer)
*/
function getOffset($page_number = 1)
{
return ($this->_pageNumber($page_number) - 1) * $this->subset_size;
}
/*
Simple counter called once per iteration.
return (bool)
*/
function isValid()
{
return (++$this->i < $this->subset_size);
}
/*
In addition to its use in _pageNumber(), this method would also be used for pagination hyperlink creation & hence isn't "private".
return (integer)
*/
function getNumPages()
{
return ceil($this->total_rows/$this->subset_size);
}
//////////////////////////////////////////
// PRIVATE //
//////////////////////////////////////////
/*
Filter invalid page numbers.
return (integer)
*/
function _pageNumber($page_number)
{
if($page_number <= 0)
{
return 1;
} elseif($page_number > $num_pages = getNumPages()) {
return $num_pages;
} else {
return $page_number;
}
}
}Setting that aside for a moment, here's Indexer in use:
Code: Select all
/*
$it (object) - a "seeking" query iterator
$indexer (object) - instance of Indexer, above
$page (integer) - a page number
*/
for($it->reset($indexer->getOffset($page)); ($it->isValid() and $indexer->isValid()); $it->next())
{
// etc
}In this way PagedQuery & PagedQueryResult can be replaced with a smaller, simpler and more focussed Indexer class alongside the normal (almost..) iterators.
Indexer deals with all the pagination arithmetic and nothing else. In the end that's all pagination is: some simple arithmetic. Perhaps this is expressed more clearly in its own, dedicated class.
Seeking Iterators
QueryIterator modified as a "Seekerator":
Code: Select all
/*
param (integer) $offset
*/
function reset($offset = 0)
{
$this->query_result->seek($offset);
$this->index = $offset;
}Code: Select all
function getRow($index, $type = ECLIPSE_DB_BOTH)
{
$this->seek($index);
++$this->currentRow;
switch ($type)
{
case ECLIPSE_DB_ASSOC:
return mysql_fetch_assoc($this->getResultId());
case ECLIPSE_DB_NUM:
return mysql_fetch_row($this->getResultId());
case ECLIPSE_DB_BOTH:
default:
return mysql_fetch_array($this->getResultId());
}
}
function seek($index)
{
if ($index != $this->currentRow)
{
mysql_data_seek($this->getResultId(), $index);
$this->currentRow = $index;
}
}