segunda-feira, 17 de setembro de 2012

Paginação com Doctrine e Zend_Framework

Olá amigos, hoje vou mostra basicamente como paginar dados usando o Zend Framework e o Doctrine, inicialmente parece algo complexo, mas vcs vão perceber que é simples.

Se vc ainda não fez uma paginação com o zend framework leia esse meu artigo sobre paginação com o ZF Paginando com Zend Framework e depois corra aqui, ou se preferir fique por aqui mesmo.

Vamos lá, vou mostrar a paginação de forma bem simples pois o grande problema de fazer um artigo sobre paginação do Zend Framework com Doctrine é que isso varia muito a arquitetura que cada um esta usando, mas nesse caso isso não vai atrapalhar pois vc vai adaptar de acordo com a sua arquitetura.

Mãos a obra

No controller....
  exemplo de consulta
  1.  public function exemploAction() {
  2.  
  3.         $request = $this->getRequest();
  4.  
  5.         if ($request->getPost()) {
  6.  
  7.             $params = $request->getPost();
  8.             $pagina = (int) $params['pag'];
  9.  
  10.             $front = \Zend_Controller_Front::getInstance();
  11.             $em = $front->getParam('bootstrap')->getResource('entityManager');
  12.             $dql = $em->createQuery("select a from Entidade_Pessoa a");
  13.  
  14.             $dados = new \DoctrineExtensions\Paginate\PaginationAdapter($dql);
  15.  
  16.             $paginator = new Zend_Paginator($dados);
  17.             // Seta a quantidade de registros por página
  18.             $paginator->setItemCountPerPage(4);
  19.             // numero de paginas que serão exibidas
  20.             $paginator->setPageRange(15);
  21.             // Seta a página atual
  22.             $paginator->setCurrentPageNumber($pagina);
  23.         }
  24.  
  25.  
  26.         $this->view->paginator = $paginator;
  27.  }

Veja que simples, usamos uma paginação aparentemente comum  do ZF não é? mas passamos para o zend_paginador a variavel $dados que contem a instância da PaginationAdapter que recebe a consulta dql e faz toda a brincadeira... esse cara esta aqui abaixo é uma classe que implementa a \Zend_Paginator_Adapter_Interface e por isso o Zend_Paginator sabe trabalhar com o objeto pois os métodos que ele usa são do nome da interface.
Lindo não é?








Veja a classe:

  ADAPTER DO DOCTRINE
  1. /**
  2.  * DoctrineExtensions Paginate
  3.  *
  4.  * LICENSE
  5.  *
  6.  * This source file is subject to the new BSD license that is bundled
  7.  * with this package in the file LICENSE. This license can also be viewed
  8.  * at http://hobodave.com/license.txt
  9.  *
  10.  * @category    DoctrineExtensions
  11.  * @package     DoctrineExtensions\Paginate
  12.  * @author      David Abdemoulaie <dave@hobodave.com>
  13.  * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
  14.  * @license     http://hobodave.com/license.txt New BSD License
  15.  */
  16.  
  17. namespace DoctrineExtensions\Paginate;
  18.  
  19. use Doctrine\ORM\Query;
  20.  
  21. /**
  22.  * Implements the Zend_Paginator_Adapter_Interface for use with Zend_Paginator
  23.  *
  24.  * Allows pagination of Doctrine\ORM\Query objects and DQL strings
  25.  *
  26.  * @category    DoctrineExtensions
  27.  * @package     DoctrineExtensions\Paginate
  28.  * @author      David Abdemoulaie <dave@hobodave.com>
  29.  * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
  30.  * @license     http://hobodave.com/license.txt New BSD License
  31.  */
  32. class PaginationAdapter implements \Zend_Paginator_Adapter_Interface {
  33.  
  34.     /**
  35.      * The SELECT query to paginate
  36.      *
  37.      * @var Query
  38.      */
  39.     protected $query = null;
  40.  
  41.     /**
  42.      * Total item count
  43.      *
  44.      * @var integer
  45.      */
  46.     protected $rowCount = null;
  47.  
  48.     /**
  49.      * Use Array Result
  50.      *
  51.      * @var boolean
  52.      */
  53.     protected $arrayResult = false;
  54.  
  55.     /**
  56.      * Constructor
  57.      *
  58.      * @param Query $query
  59.      * @param string $ns Namespace to prevent named parameter conflicts
  60.      */
  61.     public function __construct(Query $query) {
  62.  
  63.         $this->query = $query;
  64.  
  65.     }
  66.  
  67.     /**
  68.      * Set use array result flag
  69.      *
  70.      * @param boolean $flag True to use array result
  71.      */
  72.     public function useArrayResult($flag = true) {
  73.         $this->arrayResult = $flag;
  74.     }
  75.  
  76.     /**
  77.      * Sets the total row count for this paginator
  78.      *
  79.      * Can be either an integer, or a Doctrine\ORM\Query object
  80.      * which returns the count
  81.      *
  82.      * @param Query|integer $rowCount
  83.      * @return void
  84.      */
  85.     public function setRowCount($rowCount) {
  86.         if ($rowCount instanceof Query) {
  87.             $this->rowCount = $rowCount->getSingleScalarResult();
  88.         } else if (is_integer($rowCount)) {
  89.             $this->rowCount = $rowCount;
  90.         } else {
  91.             throw new \InvalidArgumentException("Invalid row count");
  92.         }
  93.     }
  94.  
  95.     /**
  96.      * Sets the namespace to be used for named parameters
  97.      *
  98.      * Parameters will be in the format 'namespace_1' ... 'namespace_N'
  99.      *
  100.      * @param string $ns
  101.      * @return void
  102.      * @author David Abdemoulaie
  103.      */
  104.     public function setNamespace($ns) {
  105.         $this->namespace = $ns;
  106.     }
  107.  
  108.     /**
  109.      * Gets the current page of items
  110.      *
  111.      * @param string $offset
  112.      * @param string $itemCountPerPage
  113.      * @return void
  114.      * @author David Abdemoulaie
  115.      */
  116.     public function getItems($offset, $itemCountPerPage) {
  117.  
  118.         $this->query->setFirstResult($offset);
  119.         $this->query->setMaxResults($itemCountPerPage);
  120.         $entities = $this->query->getResult();
  121.  
  122.         return $entities;
  123.     }
  124.  
  125.     /**
  126.      * @param Query $query
  127.      * @return int
  128.      */
  129.     public function count() {
  130.         if (is_null($this->rowCount)) {
  131.             $this->setRowCount(
  132.                     $this->createCountQuery()
  133.             );
  134.         }
  135.         return $this->rowCount;
  136.     }
  137.  
  138.     /**
  139.      * @return Query
  140.      */
  141.     protected function createCountQuery() {
  142.         return Paginate::createCountQuery($this->query);
  143.     }
  144.  
  145.     /**
  146.      * @return Query
  147.      */
  148.     protected function createLimitSubquery($offset, $itemCountPerPage) {
  149.         return Paginate::createLimitSubQuery($this->query, $offset, $itemCountPerPage);
  150.     }
  151.  
  152.     /**
  153.      * @return Query
  154.      */
  155.     protected function createWhereInQuery($ids) {
  156.         return Paginate::createWhereInQuery($this->query, $ids, $this->namespace);
  157.     }
  158.  
  159. }
Veja que nós implementamos os métodos da interface e montamos o resultado então na view é só pegar como de costume o "$this->paginator" iterar ele e mandar bala!



Dúvidas? Me avisem pois fiz esse post meio correndo... rsrs