2.3 Paginação

O que é paginação?

Uma das situações mais comuns em um sistema é a necessidade de listar dados, como uma lista de usuários por exemplo. Mas as vezes esta lista é muito grande para ser exibida em apenas uma página, por isso separamos os resultados em diversas páginas diferentes. Isso é o que chamamos de paginação.

Para fazer a paginação de uma lista precisamos pensar em alguns detalhes:

  • Temos que montar a query (consulta) no banco de dados;
  • Temos de definir os parâmetros de paginação;
  • Número de itens por página
  • Quantidade de links de páginas
  • Número da página atual
  • Montar o HTML para mostrar os resultados;

Query no Banco de Dados (SQL)

Para criar paginação a montagem da consulta SQL não deve sofrer nenhuma alteração, a única mudança é que no retorno do método do Gateway vamos retornar o objeto de paginação do SuitUp que é o método paginate da classe db, ou seja, return $this->db->paginate($query).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
namespace ModuleDefault\Model\Gateway;

use SuitUp\Database\Gateway\AbstractGateway;

class User extends AbstractGateway
{
    protected $name = 'user';
    protected $primary = array('pk_user');

    /**
     * Gera lista paginada de usuarios
     * 
     * @param array $filters Lista de filtros para a listagem
     * @return SuitUp\Paginate\Paginate
     */
    public function listaUsuarios(array $filters = array()) {

        $query = $this->select("SELECT u.* FROM {$this->name} u")
            ->columns(array(
                'id_user' => 'id',
                'name',
                'age',
                'document',
                'email',
            ))
            ->innerJoin("profile p", "p.id_profile = u.id_profile")
            ->innerJoin("sector r", "r.id_sector = p.id_sector")
            ->where("u.status = 1");

        if (isset($filters['sector']) && $filters['sector']) {
            $query->where("r.id_sector = ?", $filters['sector']);
        }

        // Esta linha é que realmente faz com que os resultados
        // da consulta sejam paginados.
        return $this->db->paginate($query);
    }
}

Parâmetros de paginação

Dentro do controlador é possível modificar algumas diretrizes da paginação como quantidade de itens por página, quantidade de links de outras páginas e número da página atual. Não é necessário mudar essas configurações, mas você pode faze-lo caso não se aplique às suas necessidades.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace ModuleDefault\Controllers;

use ModuleDefault\Model\UserBusiness;

class UserController extends AbstractController
{
    public function indexAction()
    {
        $filters = $this->getPost();

        // Note que este não é o GATEWAY,
        // Veja o porque disso em
        // https://github.com/braghimsistemas/suitup-php/wiki/5.-Banco-de-dados#business-regras-de-neg%C3%B3cio
        $userBo = new UserBusiness();
        $list = $userBo->listaUsuarios($filters);

        /** Aqui você pode mudar as configuracoes da paginação se quiser. Não é obrigatório**/

        // Número de links para outras paginas
        $list->setPageRange(7); // Padrao é 5

        // Número da página atual
        $list->setCurrentPage($this->getParam('page', 1)); // padrão = $_GET['pagina']

        // Número de itens por pagina
        $list->setNumberPerPage(100); // Padrão = 50

        $this->addViewVar(array(
            'list' => $list
        ));
    }
}

Note que acima existe a solução para um problema que pode tirar o seu sono, é o nome do parâmetro pagina que você pode querer alterá-lo. Lembre-se que para alterá-lo também é necessário modificar o HTML do arquivo aqui

Parâmetros padrão

  1. O sistema pega o $this->getParam('pagina', 1); como parâmetro de pagina atual.
  2. O range de páginas é 5. Este é o número de links para outras páginas que vai aparecer para o usuário.
  3. Quantidade de resultados por página é 50.

Métodos do objeto de paginação

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// Muda o numero total de itens que vão aparecer na lista de páginas para selecionar
public function setPageRange($pageRange);

// Pega o numero total de itens que aparecem na lista para selecionar a página
public function getPageRange();

// Indica o numero da página atual ** Por padrão pega o parametro 'pagina' da URL **
public function setCurrentPage($currentPage);

// Página atual. Pega o parametro 'pagina' da URL
public function getCurrentPage();

// Numero de resultados da query que vão aparecer em cada página.
public function setNumberPerPage($numberPerPage);
public function getNumberPerPage();

// Numero total de paginas que esta query irá retornar.
public function getTotalPages();

HTML

Mostrando o resultado

Uma vez no HTML o objeto de paginação pode ser utilizado junto a um foreach sem problemas.

Páginas

Para mostrar as páginas basta adicionar o seguinte código no seu html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!-- HTML da sua listagem -->
<table class="table table-striped">
    <tr>
        <td>ID</td>
        <td>Nome</td>
    </tr>
    <?php foreach($list as $key => $item): ?>
        <tr>
            <td><?php echo $item['id']; ?></td>
            <td><?php echo $item['nome']; ?></td>
        </tr>
    <?php endforeach; ?>
</table>
<!-- /Fim da tabela -->

<!-- Paginacao da tela -->
<?php echo paginateControl($list); ?>
<!-- /Paginacao da tela -->

HTML para paginacao

Adicione o seguinte arquivo em ModuleDefault/views/paginacao.phtml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php if(count($items)): ?>
    <nav>
        <ul class="pagination">
            <?php if($previousPage): ?>
                <li><a href="<?php echo $baseUrl; ?>pagina=<?php echo $previousPage; ?>" aria-label="Anterior"><span aria-hidden="true">&laquo;</span></a></li>
            <?php else:?>
                <li class="disabled"><a href="javascript:void(0);" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
            <?php endif; ?>

            <?php foreach($items as $key => $page): ?>
                <?php if($page != $currentPage): ?>
                    <li><a href="<?php echo $baseUrl; ?>pagina=<?php echo $page; ?>"><?php echo $page; ?></a></li>
                <?php else: ?>
                    <li class="active"><a href="javascript:void(0);"><?php echo $page; ?> <span class="sr-only">(current)</span></a></li>
                <?php endif; ?>
            <?php endforeach; ?>

            <?php if($nextPage): ?>
                <li><a href="<?php echo $baseUrl; ?>pagina=<?php echo $nextPage; ?>" aria-label="Próxima"><span aria-hidden="true">&raquo;</span></a></li>
            <?php else:?>
                <li class="disabled"><a href="javascript:void(0);" aria-label="Previous"><span aria-hidden="true">&raquo;</span></a></li>
            <?php endif; ?>
        </ul>
    </nav>
<?php endif; ?>

Lembre-se que para mudar o parâmetro pagina é necessário também capturar este parâmetro no controlador com $this->getParam('page', 1);. Veja aqui o exemplo.