доктрина 2 и зенд пагинатор

я хочу использовать доктрину с zend_paginator

вот пример запроса:

$allArticleObj = $this->_em->getRepository('Статьи'); $qb = $this->_em->createQueryBuilder();

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

Есть ли какой-нибудь пример кода, показывающий, что мы можем написать адаптер zend_paginator для построителя запросов доктрины 2?


person Sina Miandashti    schedule 09.07.2011    source источник


Ответы (4)


В результате, конечно, вам нужно реализовать Zend_Paginator_Adapter_Interface, что по сути означает реализацию двух методов:

count()

getItems($offset, $perPage)

Ваш адаптер примет запрос Doctrine в качестве аргумента конструктора.

В принципе, часть getItems() на самом деле проста. Просто добавьте к запросу ограничения $offset и $perPage — как вы делаете в своем образце — и выполните запрос.

На практике это count() бизнес, который имеет тенденцию быть сложным. Я бы последовал примеру Zend_Paginator_Adapter_DbSelect, заменив операции Zend_Db их аналогами Doctrine.

person David Weinraub    schedule 10.07.2011

Вам не нужно реализовывать Zend_Paginator_Adapter_Interface. Он уже реализован с помощью Zend_Paginator_Adapter_Iterator.

Вы можете просто передать Paginator Doctrines в Zend_Paginator_Adapter_Iterator, который вы передадите в Zend_Paginator. Затем вы вызываете Zend_Paginator::setItemCountPerPage($perPage) и Zend_Paginator::setCurrentPageNumber($current_page). Нравится:

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     
}
 

Затем вы используете paginator в сценарии просмотра, как обычно.

Объяснение:

Конструктор Zend_Paginator может принимать Zend_Paginator_Adapter_Interface, который реализует Zend_Paginator_Adpater_Iterator. Теперь конструктор Zend_Paginator_Adapter_Iterator использует интерфейс \Iterator. Этот \Iterator также должен реализовывать \Countable (как вы можете видеть, взглянув на конструктор Zend_Paginator_Adapter_Iterator). Поскольку метод Paginator::getIterator() возвращает \ArrayIterator, он по определению отвечает всем требованиям (поскольку \ArrayIterator реализует как \Iterator и \Countable).

См. этот перенос кода Zend Framework с Doctrine 1 на Doctrine 2: Руководство для начинающих с Doctrine 1 на Doctrine: https://github.com/kkruecke/zf-beginners-doctrine2. Он включает код для разбиения на страницы с помощью Zend_Paginator с использованием Zend_Paginator_Adapter_Iterator с Doctrine 2' Doctrine\ORM\Tools\Pagination\Paginator.

Код находится здесь (хотя он может не работать с последней версией DoctrineORM 2.2), но пример действителен: https://github.com/kkruecke/zf-beginners-doctrine2/tree/master/ch7

person Kurt Krueckeberg    schedule 17.02.2012
comment
Эта реализация неверна. Несмотря на то, что это работает, когда вы запускаете $d2_paginator->getIterator(), он извлекает ВСЕ объекты из базы данных, а затем Zend paginator просто отфильтровывает их. Поэтому, если у вас много записей, которые нужно разбить на страницы, этот подход будет очень медленным. - person Pavel Dubinin; 29.05.2012
comment
Согласованный. Для меня это заканчивается 502, потому что сценарий занимает слишком много времени. Это только для ~ 20K записей. Не масштабируется. - person Ian Fosbery; 11.03.2014

Я был очень удивлен, насколько сложно было найти пример адаптера, который не вызывает проблем с производительностью при работе с большими коллекциями для Doctrine 2 и ZF1.

Моя душа использует Doctrine\ORM\Tools\Pagination\Paginator из Doctrine 2.2 точно так же, как @ ответ Курта; однако разница в том, что это вернет разбиение на страницы доктрины (которое само по себе является \Iterator) из getItems без гидратации всех результатов запроса.

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);
    }

} 
person AlexP    schedule 15.06.2015

Пожалуйста измените

use Doctrine\ORM\Tools\Pagination as Paginator;

to

use Doctrine\ORM\Tools\Pagination\Paginator as Paginator;
person tridem    schedule 29.02.2012