Zend_Paginator and Zend_Db_Table

I had been waiting for a pagination component to be added to the Zend Framework for quite some time, so when Jurrien Stutterheim and Matthew Ratzloff’s proposal got accepted I couldn’t wait to give it a try, however, I came across a problems almost instantly. By default the Zend_Paginator_Adapter_DbSelect doesn’t like Zend_Db_Table_Select objects and throws the following exception: “No table has been specified for the FROM clause”.

After searching the mailing lists I came across a solution, which works by force setting the from table in the select object:

$table = new Users();
$select = $table->select()->from($table);
$paginator = Zend_Paginator::factory($select);

However, the result of the query is returned as an array rather than a Zend_Db_Table_Rowset object. The downside of this is that I often use a Zend_Db_Table/Zend_Db_Table_Row combination as my model. To make this possible I have extended the Zend_Paginator_Adapter_DbSelect class, this is the code:

class Noginn_Paginator_Adapter_DbTable extends Zend_Paginator_Adapter_DbSelect
{
    /**
     * The table to select from
     *
     * @var Zend_Db_Table
     */
    protected $_table;

    /**
     * Constructor.
     *
     * @param Zend_Db_Table_Select $select The select query
     * @param Zend_Db_Table $table The table to select from
     */
    public function __construct(Zend_Db_Table_Select $select, Zend_Db_Table $table)
    {
        $this->_select = $select;
        $this->_table = $table;
    }

    /**
     * Returns a rowset object
     *
     * @param  integer $offset Page offset
     * @param  integer $itemCountPerPage Number of items per page
     * @return Zend_Db_Table_Rowset
     */
    public function getItems($offset, $itemCountPerPage)
    {
        $this->_select->limit($itemCountPerPage, $offset);

        return $this->_table->fetchAll($this->_select);
    }

    /**
     * Returns the total number of rows in the result set.
     *
     * @return integer
     */
    public function count()
    {
        if ($this->_rowCount === null) {
            $expression = new Zend_Db_Expr('COUNT(*) AS ' . self::ROW_COUNT_COLUMN);

            $rowCount = clone $this->_select;
            $rowCount->from($this->_table)
                     ->reset(Zend_Db_Select::COLUMNS)
                     ->reset(Zend_Db_Select::ORDER)
                     ->reset(Zend_Db_Select::LIMIT_OFFSET)
                     ->columns($expression);

            $this->setRowCount($rowCount);
        }

        return $this->_rowCount;
    }
}

Example usage of the class:

$table = new Users();
$select = $table->select()->order('last_name ASC');
$paginator = new Zend_Paginator(Noginn_Paginator_Adapter_DbTable($select, $table);

This is working well for me, but I would be interested to hear of any better solutions.

On a side note I am currently looking at the Zend_Model proposal also by Jurrien Stutterheim, which so far looks fairly promising and already has a custom paginator adapter.

3 Comments

2. John posted on 01/10/2008 at 4:02 PM

Thanks for this, it clarifies nicely. However where do you place the extension, what filename do you save it as, and how is it called? I understand how the extension would work, but am having a hard time getting the Zend Framework to see the extension.

Thank you!
John

3. Tom posted on 01/10/2008 at 4:55 PM

Hi John,

I’m glad you found it useful.

If you save the Noginn_Paginator_Adapter_DbTable class to
library/Noginn/Paginator/Adapter/DbTable.php
then it should get picked loaded by the Zend_Loader autoloader.

Tom

4. John posted on 01/10/2008 at 5:44 PM

Aha! I was putting in in the wrong location, works perfect now. Thanks again!

Have your say

(Never published)
(Optional)

About the author

Tom Graham is a web developer living in Leicester, UK. This blog is his vent for all things web design and development. Read more about Tom.

Categories

Pages

Attending

phpnw08 PHP Conference 22/11/2008