Trabalhando com paginação usando Zend_Paginator
A paginação de coleções é um elemento crítico para interface de qualquer aplicação que forneça pesquisa ou outras formas de listagens, ao utilizar paginação, quebramos uma coleção em pedaços, onde cada pedaço é apresentado em uma página, impedindo que o usuário visualize uma quantidade exorbitante de itens, deixando a aplicação mais profissional.
O Zend Framework oferece um componente para realizar paginações, Zend_Paginator, que tem como princípio a flexibilidade, permitindo criar paginações a partir de vários tipos de coleções. Se você não trabalha utilizando frameworks, pode optar por desenvolver uma solução própria ou pesquisar uma solução na internet.
Fundamentos do Zend_Paginator
Este componente como foi dito é flexível e aceita diversos tipos de coleções, mas não se limita a sua flexibilidade, confira os objetivos do Zend_Paginator:
- Paginar diversos tipos de dados, não apenas bancos de dados relacionais
- Buscar apenas os resultados que precisam ser exibidos
- Não forçar os usuários a utilizar apenas uma maneira de exibir os dados ou pagina-los
- Ser fracamente acoplado aos outros componentes do Zend Framework
Para cada tipo de coleção de dados, existe um adaptador, ou seja, uma classe que fica responsável por fornecer acesso aos dados e controles de paginação, confira os adaptadores disponíveis:
Tipo | Descrição |
---|---|
Array | Utiliza um array como coleção de dados |
DbSelect | Utiliza uma instância DbSelect, retornando um array |
DbTableSelect | Utiliza uma instância DbTableSelect, retornando um rowset |
Iterator | Utiliza uma instância Iterator |
Null | Não manipula os dados, fornece apenas o controlador de páginas |
Criando uma instância do Zend_Paginator
Para criar uma instância, primeiro devemos instanciar um tipo de adaptador, passando para o seu construtor nossa coleção, após instanciar nosso adaptador, basta instanciar o Zend_Paginator passando o adaptador como parâmetro no construtor da classe.
// Action scope... $array = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); $adapter = new Zend_Paginator_Adapter_Array($array); $paginator = new Zend_Paginator($adapter);
Visando facilitar a vida do programador e padronizar a maneira que instânciamos este componente, podemos utilizar o método estático factory($data), que fica responsável por verificar o tipo de coleção que está sendo passado como parâmetro e utilizar o adaptador correto.
// Action scope... $array = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); $paginator = Zend_Paginator::factory($array);
Caso você utilize o adaptador do tipo Null, será necessário informar o número total de resultados, independente da maneira que você instanciar, seja pelo adaptador ou pelo método factory($data).
Configurações básicas do Zend_Paginator
Para personalizar a maneira que nossos dados serão apresentados ao usuário, o Zend_Paginator fornece métodos para configuração da paginação, confira alguns métodos disponíveis:
Método | Padrão | Descrição |
---|---|---|
setCurrentPageNumber | 1 | Informa o número da página atual |
setItemCountPerPage | 10 | Informa o número de itens exibidos por página |
setPageRange | 10 | Informa a quantidade de páginas visíveis na paginação |
// Action scope... $paginator->setCurrentPageNumber($this->_getParam('page')) ->setItemCountPerPage(15) ->setPageRange(15);
A quantidade de páginas pode variar dependendo do estilo escolhido, para esses casos este valor só será utilizado para iniciar o controle da paginação.
Manipulando os dados através do Zend_Paginator
Para manipular os dados, precisamos primeiro enviar nossa instância do Zend_Paginator para view.
// Action scope... $this->view->assign('paginator', $paginator);
Com essa instância disponível na view, basta iterar utilizando um foreach e imprimir seus resultados.
// View scope... <?php foreach ($this->paginator as $item): ?> <p> <?php echo $item ?> </p> <?php endforeach; ?>
Esse tipo de manipulação não irá funcionar caso você utilize um adaptador do tipo Null.
Templates e estilos de rolagem
Até agora vimos como instanciar, configurar e manipular os dados da paginação, agora iremos dar uma olhada nos templates e estilos de rolagem utilizados para gerar os controladores de paginação.
Templates de paginação
Para isso contamos com uma série de propriedades disponíveis, confira:
Propriedade | Tipo | Descrição |
---|---|---|
first | integer | Número da primeira página |
firstItemNumber | integer | Número absoluto do primeiro item desta página |
firstPageInRange | integer | Primeira página do intervalo retornado pelo estilo de rolagem |
current | integer | Número da página atual |
currentItemCount | integer | Número de itens nesta página |
itemCountPerPage | integer | Número máximo de itens disponíveis para cada página |
last | integer | Número da última página |
lastItemNumber | integer | Número absoluto do último item desta página |
lastPageInRange | integer | Última página do intervalo retornado pelo estilo de rolagem |
next | integer | Número da página seguinte |
pageCount | integer | Número de páginas |
pagesInRange | array | Conjunto de páginas retornadas pelo estilo de rolagem |
previous | integer | Número da página anterior |
totalItemCount | integer | Número total de itens |
Estilos de rolagem
Além de permitir a criação de templates, o Zend_Paginator permite escolher estilos de rolagem para exibição das páginas, o estilo especifica como deve ser o comportamento do controlador enquanto navegamos pelas páginas.
Confira a lista de estilos disponíveis:
Tipo | Descrição |
---|---|
All | Exibirá todas as opções disponíveis |
Elastic | Parecida com a paginação do google, variando de tamanho |
Jumping | Exibe novas opções ao atingir o final das opções apresentadas |
Sliding | Tenta manter a página atual no centro da paginação, mais utilizado |
Imprimindo o controlador de paginação
Para imprimir o controlador de paginação temos duas alternativas.
1. Utilizando o view helper paginationControl
// View scope ... <?php echo $this->paginationControl($this->paginator, 'Sliding', 'pagination.phtml'); ?> // ...
2. Configurando estilo e script no bootstrap ou action
// Bootstrap or Action scope ... Zend_Paginator::setDefaultScrollingStyle('Sliding'); Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination.phtml'); // ... // View scope ... <?php echo $this->paginator; ?> // ...
Caso seja adicionado no Bootstrap todos os paginators da aplicação serão configurados para utilizar esses valores como padrão, mas nada impede alterar casos específicos se necessário.
Trabalhando com paginação usando Zend_Paginator
Agora que já conhecemos um pouco sobre o Zend_Paginator, vamos criar uma paginação simples, para botar em pratica os conhecimentos deste artigo, que visa introduzir este tema. Baseado na estrutura apresentada no tópico Preparando o ambiente para desenvolvimento com Zend Framework, crie um projeto com nome de example-zend-paginator.

No exemplo que será visto agora, iremos utilizar uma tabela no banco de dados, será a tabela “user”, com dois campos user_id e name, além disso vamos precisar de alguns registros cadastrados para listar os resultados, para facilitar essa tarefa, acesse o script de criação e inserção de dados, copie este conteúdo, acesse o phpmyadmin, http://localhost/phpmyadmin, crie uma base de dados com o nome de “zf-paginator” e adicione o conteúdo do script para criar a tabela e seus registros.
Configure a aplicação para acessar o banco de dados “zf-paginator”, caso tenha dúvida, visualize o artigo Entendendo modelos no zend framework.
Criando nosso modelo
Crie o arquivo User.php na pasta “application/models” e adicione o seguinte conteúdo:
User.php
<?php class User extends Zend_Db_Table_Abstract { /** * The default table name */ protected $_name = 'user'; }
Criando nosso controller e action
Neste exemplo iremos criar o controlador UserController.php contendo uma action, nomeada de list( listAction ), ou seja, utilizaremos a view list.phtml, o template que vamos utilizar será do tipo search, disponível na documentação do componente.
Adicione o arquivo “UserController.php” na pasta “application/controllers” com o seguinte conteúdo:
UserController.php
<?php class UserController extends Zend_Controller_Action { public function listAction() { $page = $this->_getParam('page', 1); $userModel = new User(); $users = $userModel->fetchAll(); $paginator = Zend_Paginator::factory($users); $paginator->setCurrentPageNumber($page) ->setItemCountPerPage(10); Zend_Paginator::setDefaultScrollingStyle('Sliding'); Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination.phtml'); $this->view->assign('paginator', $paginator); } }
Agora vamos preparar nossa view, crie uma pasta nomeada de “user” em “application/views/scripts” e depois adicione o arquivo list.phtml com o seguinte conteúdo:
list.phtml
<ul> <?php if(sizeof($this->paginator)): ?> <?php foreach($this->paginator as $user): ?> <li><?php echo $this->escape($user->name); ?></li> <?php endforeach; ?> <?php else: ?> <li>Nenhum usuário encontrado.</li> <?php endif; ?> </ul> <?php echo $this->paginator; ?>
Nesse momento só falta nosso template de paginação, adicione o arquivo pagination.phtml em “application/views/scripts” com o seguinte conteúdo:
pagination.phtml
<?php if ($this->pageCount): ?> <div> <!-- Previous page link --> <?php if (isset($this->previous)): ?> <a href="<?php echo $this->url(array('page' => $this->previous)); ?>"> < Previous </a> | <?php else: ?> <span>< Previous</span> | <?php endif; ?> <!-- Numbered page links --> <?php foreach ($this->pagesInRange as $page): ?> <?php if ($page != $this->current): ?> <a href="<?php echo $this->url(array('page' => $page)); ?>"> <?php echo $page; ?> </a> | <?php else: ?> <?php echo $page; ?> | <?php endif; ?> <?php endforeach; ?> <!-- Next page link --> <?php if (isset($this->next)): ?> <a href="<?php echo $this->url(array('page' => $this->next)); ?>"> Next > </a> <?php else: ?> <span>Next ></span> <?php endif; ?> </div> <?php endif; ?>
Estrutura final do nosso projeto:

Resultado
Ao acessar nossa action list do controller user, teremos o seguinte resultado:

Caso seja clicado no link para página 2 ou em next, iremos obter outra lista de resultado, confira:

Visualizar ou efetuar download do exemplo, lembrando que no repositório desse projeto no github não consta os arquivos do framework.
Comentários 15
Felipe Gama
31/10/2011 às 12:01
Parabéns Diogo, excelente!
Ajudou muito cara, facilitou o entendimento de uma forma enorme…
Obrigado.
DEUS O ABENÇOE
Diogo Matheus
01/11/2011 às 21:52
Muito obrigado Felipe.
Wanderson
06/12/2011 às 12:09
Ótimo tópico Diogo,
Mas dessa maneira se consome muito recurso, pois todos os dados da tabela são carregados.
Tem como fazer a paginação como o Zend_Paginator de maneira a trazer somente os dados que realmente serão exibidos?
Diogo Matheus
06/12/2011 às 12:32
Olá Wanderson,
Exatamente, está não é a melhor pratica para utilizar paginação com o Zend_Paginator.
No final do artigo eu comento sobre isso, o objetivo desse artigo foi introduzir como realmente funciona o paginador, adaptadores e etc. O exemplo que botei é como costuma ser visto pela internet, no próximo artigo irei mostrar como criar paginações otimizadas.
Mas adiantando, uma boa pratica seria passar um objeto da classe Zend_Db_Select, onde o adapter iria manipular o objeto adicionando limites baseados na página que deve ser exibida.
Abraço e boa sorte.
Wanderson
07/12/2011 às 14:01
Beleza Diogo,
Estarei sempre visitando seu blog para ver as novidades.
Um grande abraço!
Diogo Matheus
07/12/2011 às 14:03
Valeu Wanderson, abraço.
Otimizando paginações com Zend_Paginator | Diogo Matheus Blog
19/12/2011 às 08:57
[…] (typeof(addthis_share) == "undefined"){ addthis_share = [];} Continuando o artigo Trabalhando com paginação usando Zend_Paginator, no qual abordamos o uso básico de paginações com Zend_Paginator, neste artigo iremos falar […]
Thiago
01/01/2012 às 02:49
Diogo, otimas dicas!! Contudo, estou fazendo um site com uma relação de produtos com fotos, mas as fotos não carregam alem da primeira pagina! Sabe oque pode ser?
ex:
<img src="” />
Abracos!!!
Flávio
04/01/2012 às 11:47
Parabéns pelo artigo. Me ajudou bastante
Diogo Matheus
04/01/2012 às 11:55
Thiago,
Você está utilizando url absoluta? tente utilizar o helper baseUrl(); no endereço da imagem (src).
Abraço e boa sorte.
Diogo Matheus
04/01/2012 às 11:56
Obrigado Flávio, que bom que te ajudou.
yure
23/10/2013 às 16:02
Tem como paginar com Scroll, deixando-o no estilo do facebook ? O zend oferece algum suporte quanto a isso ?
Joe
02/07/2014 às 19:31
Artigo TOP!!! Obrigado! Deus lhe abençoe!
Diogo Matheus
26/02/2015 às 15:18
Joe,
Obrigado pelo comentáro.
Luiz Henrique Dapieve
20/01/2017 às 13:23
Olá Diogo, primeiramente quero agradecer pelo ótimo artigo.
Enfrentei alguns problemas para encontrar uma solução com Paginator, e com esse artigo pensei em outra maneira de usar e estou postando esse comentário também para ajudar alguém.
Estava construindo uma query bem complexa e com alguns innnerJoins e para facilitar eu precisava utilizar o “Doctrine::HYDRATE_SCALAR”, mas o paginator se perdia para fazer a contagem dos resultados então com seu artigo consegui resolver o problema da seguinte forma :
$query = UserTable::getInstance()->list($options); (Retorna a Query)
$query->setHydrationMode(Doctrine::HYDRATE_SCALAR);
//Criação do Adapter para funcionar o Paginator com HYDRATE_SCALAR
$adapter = new Zend_Paginator_Adapter_Array($query->execute());
$paginator = new Application_Paginator_Paginator($adapter, $page);
Espero que esse trecho também ajude quem precise.
Obrigado. Abraço.