Zend Framework: Paginando resultados de uma consulta com o Zend_Paginator

Introdução

Esse tutorial tem como objetivo mostrar passo-a-passo como paginar resultados de uma consulta, quando executada como o Zend Framework, utilizando o componente Zend_Paginator, uma vez que essa parte da documentação está um pouco superficial. 

  • Versões utilizadas:
  • Apache 2.2.10
  • PHP 5.2.6
  • Postgres 8.3
  • Zend Framework 1.6.2 

Conceitos

O Zend_Paginator é um controle de paginação que é capaz de tratar três tipos de resultados:

  • Array - um array qualquer do PHP
  • Select - uma instância do Zend_Db_Select
  • Iterator - uma instância da classe Iterator

 

Para cada um desses resultados, existe um Adapter para o Zend_Paginator que deve ser passada no momento da criação. Veja: 

<span style="color: rgb(0, 0, 0);">$paginator&nbsp;=&nbsp;new&nbsp;Zend_Paginator(new&nbsp;Zend_Paginator_Adapter_Array($array));</span>

 

Como o nosso foco aqui é paginar o resultado de uma pesquisa, então devemos utilizar o Select:

<span style="color: rgb(0, 0, 0);">$paginator&nbsp;=&nbsp;new&nbsp;Zend_Paginator(new&nbsp;Zend_Paginator_Adapter_Select($select));</span>

 

Uma forma mais fácil para paginar suas informações é utilizando o método factory para criar o paginador:

<span style="color: rgb(0, 0, 0);">$paginator&nbsp;=&nbsp;Zend_Paginator::factory($array);</span>

ou

<span style="color: rgb(0, 0, 0);">$paginator&nbsp;=&nbsp;Zend_Paginator::factory($select);</span>

 

O método factory irá identificar o tipo de resultado automaticamente e instanciará a classe responsável por adaptar o resultado.

 

O Controller

Como o foco desse tutorial é para paginar o resultado de uma consulta a um banco de dados, vamos utilizar uma estrutura como exemplo:

CREATE TABLE usuarios (
	codigo SERIAL,
	nome VARCHAR(40),
	senha CHAR(32),
	email TEXT
);

 

Nesse tutorial, vamos assumir que a conexão do banco de dados foi feita e armazenada dentro de uma variável $db, portanto, no nosso IndexController, vamos trabalhar no action indexAction. Assumimos também que não devemos nesse momento nos importar sobre o que vamos utilizar como filtro, bem como montagem do formulário, e tudo mais. Vamos focar apenas a pginação de resultados.

Dentro da action precisamos então utilizar uma instância do Zend_Db_Select para passar para o paginador:

$select = $db->select()->from('usuarios');

 

Tendo o select pronto, criamos o paginador:

$paginator = Zend_Paginator::factory($select);

 

Após criado o paginador, configuramos com a página atual e a quantidade de registros por página:

$pagina = $this->_getParam('pagina', 1);
$paginator->setCurrentPageNumber($pagina);
$paginator->setItemCountPerPage(10);

 

Depois é só passar para a view o componente de paginação:

$this->view->paginator = $paginator;

 

Essas alterações bastam no controller, sendo concluído dessa forma:

<?php

class IndexController extends Zend_Controller_Action 
{
    public function indexAction() 
    {
        $db = Zend_Registry::get('db');
        $select = $db->select()->from('usuarios');
        $pagina = $this->_getParam('pagina', 1);
        
        $paginator = Zend_Paginator::factory($select);
        $paginator->setCurrentPageNumber($pagina);
        $paginator->setItemCountPerPage(10);
        
        $this->view->paginator = $paginator;
    }
}

 

A View

Vamos fazer uma view simples, que apenas lista os resultados.

Para verificar se há resultados em nossa busca utilize, dentro da view:

<?php if (count($this->paginator)): ?>

 

Para receber cada linha de resultado, use o foreach:

<?php foreach ($this->paginator as $item): ?>
  <li><?= $item['nome']; ?> - <?= $item['usuario']; ?> - <?= $item['email']; ?></li>
<?php endforeach; ?>

 

E para imprimir os controles de paginação (anterior, próxima, etc) é preciso indicar um arquivo HTML que contem apenas o trecho dos controles, e indicar o estilo da paginação. Para isso deve-se utilizar o helper paginationControl. Veja:

<?= $this->paginationControl($this->paginator, 'Sliding', 'index/controles_paginador.phtml'); ?>

O estilo de paginação, passado como segundo parâmetro, se refere ao comportamento da exibição dos números das páginas enquanto forem navegadas. Veja uma explicação para cada estilo disponível:

  • All - Mostra todos os números de páginas geradas pela paginação de resultados
  • Elastic - Ao chegar no último números, mais números de páginas são exibidos, junto com os outros.
  • Jumping - Ao chegar no último número da página, esse número passa a ser o primeiro a ser exibido, e são exibidas mais N páginas.
  • Sliding - A página atual fica no centro dos números das páginas.

No final a nossa view ficou assim:

<html>
    <body>
        <h1>Usuários</h1>
        <?php if (count($this->paginator)): ?>
        <ul>
        <?php foreach ($this->paginator as $item): ?>
            <li><?= $item['nome']; ?> - <?= $item['usuario']; ?> - <?= $item['email']; ?></li>
        <?php endforeach; ?>
        </ul>
        <?php endif; ?>
        <?= $this->paginationControl($this->paginator, 'Sliding', 'index/controles_paginador.phtml'); ?>
    </body>
</html>

 

O Partial

Ainda precisamos criar os controles do paginador. Os controles serão criados em um partial, que é o nomes que damos a um trecho de view separado em outro arquivo, que pode ser acoplado a outras views. O partial indicado na view que criamos é é o controle_paginador.phtml e nele teremos acesso as propriedades:

$this->pageCount; //total de páginas
$this->previous; //página anterior
$this->pagesInRange; //páginas a serem mostradas para acesso pelo clique no número
$this->current; //página atual
$this->next; //próxima página

 

Com acesso as propriedades acima, mesclando com uma lógica qualquer, podemos formar um partial como o abaixo:

<?php if ($this->pageCount): ?> 
    <div class="paginationControl">
    <!-- Página anterior --> 
    <?php if (isset($this->previous)): ?> 
        <a href="<?= $this->url(array('pagina' => $this->previous)); ?>">&lt; Anterior</a> | 
    <?php else: ?> 
        <span class="disabled">&lt; Anterior</span> | 
    <?php endif; ?> 

    <!-- numeração -->
    <?php foreach ($this->pagesInRange as $page): ?> 
        <?php if ($page != $this->current): ?>
        <a href="<?= $this->url(array('pagina' => $page)); ?>"><?= $page; ?></a> | 
          <?php else: ?>
        <?= $page; ?> | 
          <?php endif; ?>
    <?php endforeach; ?>

    <!-- Próxima --> 
    <?php if (isset($this->next)): ?> 
          <a href="<?= $this->url(array('pagina' => $this->next)); ?>">P&oacute;xima &gt;</a>
    <?php else: ?> 
        <span class="disabled">P&oacute;xima &gt;</span>
    <?php endif; ?> 
    </div> 
<?php endif; ?>

Note que para os links utilizamos o helper url() passando o parâmetro pagina (o número da página a ser exibida).

Pronto. Basta acessar seu projeto na sua aplicação que tera os resultados paginados.

Para maiores informações sobre o funcionamento do Zend_Paginator, consulte o manual de referência:

http://framework.zend.com/manual/en/zend.paginator.html