Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

doctrine 2 and zend paginator

i want to use doctrine with zend_paginator

here some example query :

$allArticleObj = $this->_em->getRepository('Articles'); $qb = $this->_em->createQueryBuilder();

    $qb->add('select', 'a')
            ->add('from', 'Articles a')
            ->setFirstResult(0)
            ->setMaxResults(5);

is there any example code to show we can write a zend_paginator adapter for doctrine 2 query builder?

like image 573
Sina Miandashti Avatar asked Jul 09 '11 14:07

Sina Miandashti


2 Answers

You don't need to implement Zend_Paginator_Adapter_Interface. It is already implement by Zend_Paginator_Adapter_Iterator.

You can simply pass Doctrines' Paginator to Zend_Paginator_Adapter_Iterator, which you pass to Zend_Paginator. Then you call Zend_Paginator::setItemCountPerPage($perPage) and Zend_Paginator::setCurrentPageNumber($current_page). Like this:

use Doctrine\ORM\Tools\Pagination as Paginator; // goes at top of file

SomeController::someAction() 
{
 $dql = "SELECT s, c FROM Square\Entity\StampItem s JOIN s.country c ".' ORDER BY '.  $orderBy . ' ' . $dir;
 
 $query = $this->getEntityManager()->createQuery($dql);
 $d2_paginator = new Paginator($query); \\
 
 $d2_paginator_iter = $d2_paginator->getIterator(); // returns \ArrayIterator object
 
 $adapter =  new \Zend_Paginator_Adapter_Iterator($d2_paginator_iter);
  
 $zend_paginator = new \Zend_Paginator($adapter);          
                       
 $zend_paginator->setItemCountPerPage($perPage)
            ->setCurrentPageNumber($current_page);

 $this->view->paginator = $zend_paginator; //Then in your view, use it just like your currently use     
}
 

Then you use paginator in the view script just like you ordinarly do.

Explanation:

Zend_Paginator's constructor can take a Zend_Paginator_Adapter_Interface, which Zend_Paginator_Adpater_Iterator implements. Now, Zend_Paginator_Adapter_Iterator's constructor takes an \Iterator interface. This \Iterator must also implement \Countable (as you can see by looking at Zend_Paginator_Adapter_Iterator's constructor). Since Paginator::getIterator() method returns an \ArrayIterator, it by definition it fits the bill (since \ArrayIterator implements both \Iterator and \Countable).

See this port from Doctrine 1 to Docrine 2 of the code for "Zend Framework: A Beginner's Guide" from Doctrine 1 to Doctrine: https://github.com/kkruecke/zf-beginners-doctrine2. It includes code for paginating with Zend_Paginator using Zend_Paginator_Adapter_Iterator with Doctrine 2' Doctrine\ORM\Tools\Pagination\Paginator.

Code is here (although it might not all work with latest DoctrineORM 2.2) but the example is valid: https://github.com/kkruecke/zf-beginners-doctrine2/tree/master/ch7

like image 182
Kurt Krueckeberg Avatar answered Sep 19 '22 22:09

Kurt Krueckeberg


I was very surprised how hard it was to find an adapter example that doesn't cause performance issues with large collections for Doctrine 2 and ZF1.

My soultion does use the the Doctrine\ORM\Tools\Pagination\Paginator from Doctrine 2.2 just like @Kurt's answer; however the difference that this will return the doctrine paginator (Which is it's self an \Iterator) from getItems without the entire query results being hydrated.

use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;
use Doctrine\ORM\Query;

class DoctrinePaginatorAdapter implements \Zend_Paginator_Adapter_Interface
{
    protected $query;

    public function __construct(Query $query)
    {
        $this->query = $query;
    }

    public function count()
    {
        return $this->createDoctrinePaginator($this->query)->count();
    }

    public function getItems($offset, $itemCountPerPage)
    {
        $this->query->setFirstResult($offset)
                    ->setMaxResults($itemCountPerPage);

        return $this->createDoctrinePaginator($this->query);
    }

    protected function createDoctrinePaginator(Query $query, $isFetchJoinQuery = true)
    {
        return new DoctrinePaginator($query, $isFetchJoinQuery);
    }

} 
like image 28
AlexP Avatar answered Sep 21 '22 22:09

AlexP