Muitas vezes nos deparamos com a necessidade de criar uma paginação de resultado, devido a grande quantidade de informações e que acaba muitas vezes prejudicando a performance da aplicação. Para evitar este tipo de problemas incluímos uma paginação, para dividir a exibição de uma grande quantidade de dados em pequenas partes.

Para os profissionais que não utilizam um framework resta a tarefa de desenvolver uma classe de paginação (que não é difícil) ou procurar no Oraculo algo pronto e que atenda a sua necessidade. Já para os programadores que utilizam o Zend Framework como base de seus projetos, podem utilizar o componente Zend_Paginator, que é um componente flexível para paginar coleções de dados e apresentar estes dados para os usuários.

Vamos agora entender um pouco do funcionamento deste componente.

Vamos iniciar pelo Controller, pois o mesmo será o passo inicial para que todo o resto funcione. No Controller iremos obter os registros do banco de dados, lembrando que não necessariamente as informações a serem paginadas devem vir de um banco de dados, pode ser informado um array contendo as informações. Tendo os registros iremos obter o objeto Zend_Paginator informando a ele os dados a serem paginados assim como as definições como, por exemplo, quantidade de registros por paginas e página atual.

Segue o exemplo do Controller:

<?php
class UsuariosController extends Zend_Controller_Action {

    public function init() {
        $this->db = Zend_Registry::get('db');
    }

    public function indexAction() {

        $pagina = intval($this->_getParam('pagina', 1));

        $select = $this->db->select()->from('usuarios');
        $dados = $select->query()->fetchAll();
               
        $paginator = Zend_Paginator::factory($dados);
        // Seta a quantidade de registros por página
        $paginator->setItemCountPerPage(10);
        // numero de paginas que serão exibidas
        $paginator->setPageRange(7);
        // Seta a página atual
        $paginator->setCurrentPageNumber($pagina);
        // Passa o paginator para a view
        $this->view->paginator = $paginator;
    }
}

Como podemos observar no exemplo acima que o Zend_Paginator nos fornece alguns métodos para configuração da paginação, como por exemplo:

setItemCountPerPage – Número máximo de registro a serem exibidos por página, por padrão o Zend utiliza 10;
setPageRange – Número de páginas a serem exibidas no menu de navegação, o padrão também é 10 itens;
setCurrentPageNumber – Informa o número da página atual, caso não seja informado o Zend assume a primeira página a ser exibida.

Seguindo o processo, vamos dar uma analisada na view, onde iremos fazer a listagem dos dados e onde será exibido o menu de paginação.

Segue o exemplo da View:

<?php foreach ($this->paginator as $dados): ?>
    <p>
        <?php echo 'Nome: ' . $dados['nome'] . ' - Usuário: ' . $dados['usuario']; ?>
    </p>
<?php endforeach; ?>

<?php echo $this->paginationControl($this->paginator, 'Sliding', 'pagination.phtml'); ?>

Vamos ter um foreach para percorrer os dados, algo bem simples, nada de muito complexo neste trecho. E para exibir a paginação iremos utilizar o Zend_View_Helper paginationControl que é o responsável em controlar a paginação.

Tendo como primeiro parâmetro a instância do paginador;

O segundo parâmetro é o estilo de nossa paginação existe as opções:

All – Será exibidas todas as páginas;
Elastic – Parecida com a paginação do Google, conforme o usuário vai navegando através da paginação ela vai expandindo ou encolhendo;
Jumping – Conforme vai navegando através da paginação ao chegar ao final do número das paginas exibidas, inicia com uma nova sequencia de números;
Sliding – Este é o estilo que utilizo por padrão em meus projetos, pois o mesmo posiciona sempre a pagina atual ao centro, ou o mais próximo dela. É o estilo que podemos observar na grande maioria das classes de paginação;

O terceiro parâmetro é o nosso modelo, template ou ainda uma visão parcial da paginação, sendo que a estrutura HTML de nossa paginação será baseada neste arquivo de template.

Segue o exemplo do template:

<div class="pagination">
    <!-- Link para a primeira página -->
    <?php if (isset($this->previous)): ?>
        <a title="Primeira Página" href="<?php echo $this->url(array('pagina' => $this->first)); ?>">&laquo; Primeira</a>|
    <?php else: ?>
        <a class="current" title="Primeira Página" href="<?php echo $this->url(array('pagina' => $this->first)); ?>">&laquo; Primeira</a>|
    <?php endif; ?>

    <!-- Link para a página anterior -->
    <?php if (isset($this->previous)): ?>
        <a title="Página Anterior" href="<?php echo $this->url(array('pagina' => $this->previous)); ?>">&laquo; Anterior</a>|
    <?php else: ?>
        <a  class="current" title="Página Anterior" href="<?php echo $this->url(array('pagina' => $this->previous)); ?>">&laquo; Anterior</a>|
    <?php endif; ?>

    <!-- Links numerados -->
    <?php foreach ($this->pagesInRange as $page): ?>
        <?php if ($page != $this->current): ?>
            <a title="<?php echo $page; ?>" href="<?php echo $this->url(array('pagina' => $page)); ?>"><?php echo $page; ?></a>|
        <?php else: ?>
            <a class="current" title="<?php echo $page; ?>" href="<?php echo $this->url(array('pagina' => $page)); ?>"><?php echo $page; ?></a>|
        <?php endif; ?>
    <?php endforeach; ?>

    <!-- Link para a Próxima página -->
    <?php if (isset($this->next)): ?>
        <a title="Próxima Página" href="<?php echo $this->url(array('pagina' => $this->next)); ?>">Próxima &raquo;</a>|
    <?php else: ?>
        <a class="current" title="Próxima Página" href="<?php echo $this->url(array('pagina' => $this->next)); ?>">Próxima &raquo;</a>|
    <?php endif; ?>

    <!-- Última página -->
    <?php if (isset($this->next)): ?>
        <a title="Última Página" href="<?php echo $this->url(array('pagina' => $this->last)); ?>">Última &raquo;</a>
    <?php else: ?>
        <a class="current" title="Última Página" href="<?php echo $this->url(array('pagina' => $this->last)); ?>">Última &raquo;</a>
    <?php endif; ?>
</div>

Por padrão deixo este arquivo dentro do diretório scripts para que o mesmo esteja disponível para todas as views do projeto.

/application/views/scripts/pagination.phtml

Segue uma descrição das propriedades utilizadas e disponíveis:

first – Número da primeira página;
firstItemNumber – Número absoluto do primeiro item nesta página;
firstPageInRanger – Primeira página no intervalo retornada pelo estilo;
current – Número da página atual;
currentItemCount – Número de itens nesta página;
last – Número da última página;
lastItemNumber – Número absoluto do último item nesta página;
lastPageInRange – Última página no intervalo retornado pelo estilo;
next – Número da próxima página;
pageCount – Número de páginas;
pagesInRange – Array de páginas retornado pelo estilo;
previous – Número da página anterior;
totalItemCount – Número total de itens;

Com esta quantidade de propriedades disponíveis podemos fazer vários modelos de paginação, bastando apenas boa criatividade para monta-la.

Deixo abaixo a imagem com o resultado final da minha paginação.
Imagem de exemplo da paginação

Restando duvidas, entre em contato.

Até breve.
Forte abraço.

14 Responses to “Criando paginação de resultados com Zend_Paginator”

  1. José Gustavo says:

    É isso aí, simples e prático.

    Obrigado,

  2. Muito show… tem como disponibilizar esse CSS do paginator?

  3. Ismael says:

    Valeu, irmãaaaao!
    Tava louco, procurando por isso.
    Continue com as postagens.
    Sucesso!

  4. Muito bom o tutorial, quem quiser um css semelhante, segue em anexo:

    /************************
    ** Pagination
    **/

    div.pagination{
    font-family: Arial,Helvetica,sans-serif;
    font-size: 12px;
    margin-top:10px;
    text-align: center;
    }

    div.pagination .currentPage {
    padding: 5px;
    background-color: #069;
    color: white;
    font-weight: bold;
    }

    div.pagination .numberPage {
    padding: 5px;
    border: 1px solid #069;
    color: #069;
    font-weight: bold;
    }

    div.pagination .numberPage:hover {
    background-color: yellow;
    }

    É necessario renomear a class current utilizada dentro do foreach para currentPage, e no mesmo if adicionar uma classe numberPage.

    Att. Felipe

  5. Legal e funcional. Vc poderia me enviar o CSS da paginação? Pode enviar para meu email.
    Obrigado

  6. Diego Pereira Grasssato says:

    Segue um CSS Igual ao utilizado…

    div.pagination{
    font-family: Arial,Helvetica,sans-serif;
    font-size: 11px;
    text-align: center;
    }

    div.pagination .currentPage {
    padding:4px;
    background-color: #069;
    color: white;
    font-weight: bold;
    border-radius: 4px;
    margin-left: 3px;
    margin-right: 3px
    }

    div.pagination .numberPage {
    padding: 3px;
    border: 1px solid #069;
    color: #069;
    border-radius: 4px;
    text-align: center;
    margin-left: 3px;
    margin-right: 3px
    }

    div.pagination .numberPage:hover {
    text-align: center;
    }


    previous)): ?>
    <a title="Primeira Pagina " class="numberPage" href="url(array(‘pagina’ => $this->first)); ?>”> Primeira 

    <a class="currentPage" title="Primeira Pagina " href="url(array(‘pagina’ => $this->first)); ?>”> Primeira 


    previous)): ?>
    <a title="Pagina Anterior " class="numberPage" href="url(array(‘pagina’ => $this->previous)); ?>”> Anterior 

    <a class="currentPage" title="Pagina Anterior " href="url(array(‘pagina’ => $this->previous)); ?>”> Anterior 


    pagesInRange as $page): ?>
    current): ?>
    <a title="” class=”numberPage” href=”url(array(‘pagina’ => $page)); ?>”>  

    <a class="currentPage" title="” href=”url(array(‘pagina’ => $page)); ?>”>  


    next)): ?>
    <a title="Proxima Pagina" class="numberPage" href="url(array(‘pagina’ => $this->next)); ?>”> Próxima 

    <a class="currentPage" title="Proxima Pagina" href="url(array(‘pagina’ => $this->next)); ?>”> Próxima 


    next)): ?>
    <a title="Ultima Pagina" class="numberPage" href="url(array(‘pagina’ => $this->last)); ?>”> Última 

    <a class="currentPage" title="Ultima Pagina" href="url(array(‘pagina’ => $this->last)); ?>”> Última 

    current; ?> de pageCount.” – Total Registros: “; echo $this->totalItemCount; ?>

  7. Átila says:

    Otimo artigo parabens, agora tenho uma dúvida referente ao link a paginação so funciona se o link estiver nesse tipo:
    http://quick.com.br/post/index/pagina/1
    ou pode ser feito algo mais amigavel tipo
    http://quick.com.br/post/1 ou
    http://quick.com.br/post/pagina/1

    Obrigado, e parabens

  8. Ótimo tutto!!! Simples e funcional! Perfeito.

  9. Joao Silva says:

    Imagina se o seu fetchAll retornar 1 milhão de registros … Coitado do processador

    • Wescley Costa says:

      E cadê o seu artigo melhor??
      É fácil criticar né… agora contribuir com a comunidade são poucos, e ainda assim, são obrigados a receberem comentários totalmente desnecessários como esse aí acima…
      Fale menos e faça mais parceiro, seja útil e não fútil…

      Abraço!

Leave a Reply

*

Current month ye@r day *