programação,

Entendendo paginação com Zend_Paginator

Diogo Matheus Diogo Matheus Seguir 31/10/2011 · 10 minutos de leitura
Entendendo paginação com Zend_Paginator
Compartilhar

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.

<?php
// 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.

<?php
// 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
<?php
// 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.

<?php
// 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

O template de paginação é responsável por definir a estrutura utilizada para exibir as páginas disponíveis em uma determinada paginação, na documentação oficial deste componente são apresentadas algumas alternativas, mas você também pode criar seu próprio template. 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

<?php
// 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.

Estrutura do projeto

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)); ?>">
    &lt; Previous
  </a> |
<?php else: ?>
  <span>&lt; 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 &gt;
  </a>
<?php else: ?>
  <span>Next &gt;</span>
<?php endif; ?>
</div>
<?php endif; ?>

Estrutura final do nosso projeto:

Estrutura final do projeto

Resultado

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

Resultado, primeira página

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

Resultado, segunda página

Confira o código-fonte do exemplo no GitHub.

Este exemplo não está otimizado para casos de grande quantidade de registros, para saber como otimizar sua paginação, não deixe de visitar o próximo artigo: Otimizando paginações com Zend_Paginator.