Paginação De Resultados

Olá Senhoras e Senhores, andei precisando fazer uma paginação nos resultados de uma consulta esse dia, então resolvi criar um esquema pra agilizar o meu processo, estou compartilhando o código, aceito sugestões para melhora, claro .. também pensei em paginar não só resultados de banco, mas sim dados retornados de um XML ou de um Array .. qualquer coisa que você possa fazer um limite, segue o código:



<?php

      class Paginator{

             /**
              * $nextPage guarda o valor da próxima página, ou zero se não houver próxima.
              * $previousPage guarda o valor da página anterior, ou zero se não houver anterior.
              * $currentPage guarda o valor da página atual
              * @var  Integer  $nextPage
              * @var  Integer  $previousPage
              * @var  Integer  $currentPage
              */
             protected $nextPage , $previousPage , $currentPage;
             /**
              * $amount guarda a quantidade de resultados para paginar
              * $limit guarda o limite de resultados por página
              * $pages guarda a quantidade de páginas 
              * @var  Integer  $amount
              * @var  Integer  $limit
              * @var  Array  $pages
              */
             protected $amount , $limit , $results = Array();
             /**
              * Setamos a quantidade de resultados que vão ser paginados logo que construímos a classe
              * esse valor pode vir de vários lugares, de um parâmetro na url ,da quantidade de registros 
              * retornados do banco , da quantidade de itens em um array 
              * @param Integer $amount 
              */
             public function __construct( $amount ){
                    if( is_numeric( $amount ) && $amount != false )
                           $this->amount = $amount;
                    else
                           throw new InvalidArgumentException( 'Esperavamos um número positivo' );
             }
             /**
              * Seta o limite de resultados por página, para fazer o calculo de páginas
              * @param Integer $Limit 
              * @return Paginator
              */
             public function setLimit( $Limit ){
                    if( !isset( $Limit ) && !is_numeric( $Limit ) )
                           throw new InvalidArgumentException ( 'Esperavamos um limite, positivo' );
                    else
                           $this->limit = $Limit;
                           for( $i = 0, $x = 1, $a = $this->getAmount(); $i < $a; $i += $this->getLimit(), ++$x ){
                                     $this->results[ 'pages' ][] = $x;
                                     $this->results[ 'limit' ][] = ( $i !== 0 ) ? $i : 1;
                           }
                           return $this;
             }
             /**
              * Removemos tudo que não é númerico da página atual, assim garantimos
              * a presença de somente númericos na propiedade da página corrente
              * @param  Integer  $Page
              * @return Paginator 
              */
             public function setPage( $Page ){
                    $this->currentPage = !is_null( $Page ) ? preg_replace( '/[^\d+]/' , null , $Page ) : 0;
                    $this->nextPage = $this->getNextPage();
                    $this->previousPage = $this->getPreviousPage();
                    return $this;
             }
             /**
              * Recupera a quantidade de resultados que serão paginados
              * @return  Integer  $this->amount
              */
             public function getAmount( ){
                    return $this->amount;
             }
             /**
              * Recupera a quantidade de resultados que serão exibidos em cada página
              * @return  Integer  $this->limit
              */
             public function getLimit( ){
                    return $this->limit;
             }
             /**
              * Recupera a página atual que está sendo visualizada
              * @return  Integer  $this->currentPage
              */
             public function getPage( ){
                    return isset( $this->currentPage ) ? $this->currentPage : 1;
             }
             /**
              * Recupera a próxima página se existir, se não retorna 0
              * @return Integer
              */
             public function getNextPage( ){
                    return $this->hasNextPage() ? ( $this->getPage() + 1 ) : 0;
             }
             /**
              * Recupera a página anterior se existir, se não retorna 0
              * @return Integer
              */
             public function getPreviousPage( ){
                    return $this->hasPreviousPage() ? ( $this->getPage() - 1 ) : 0;
             }
             /**
              * Retorna true se existir uma próxima página
              * @return Boolean 
              */
             public function hasNextPage(){
                    return ( max( $this->results[ 'pages' ] ) >= $this->getPage() + 1 );
             }
             /**
              * Retorna true se exitir uma página anterior
              * @return Boolean
              */
             public function hasPreviousPage(){
                    return ( min( $this->results[ 'pages' ] ) <= $this->getPage() - 1 );
             }
             /**
              * Gera os links para navegação 
              * @param Mixed $path
              * @param Mixed $param 
              */
             public function renderNavigation( $path , $param ){
                    for( $i = 0; $i < count( $this->results[ 'pages' ] ) ; ++$i ){
                           printf( '<a href="%s?%s=%d">%d</a>' , $path , $param , $this->results[ 'pages' ][ $i ] , $this->results[ 'pages' ][ $i ] );
                    }
             }
             /**
              * Remove todas as propriedades existentes nessa classe
              */
             public function unsetPropertys(){
                    $ReflectionClass = new ReflectionClass( $this );
                    foreach( $ReflectionClass->getProperties() as $Property ){
                             if( $Property->class == array_pop( explode( '\\' , get_class( $this ) ) ) ){
                                    unset( $this->{$Property->getName()} );
                             }
                    }
             }
             /**
              * Recupera o limite de resultados baseado na página atual 
              * vezes o número de resultados a serem exibidos
              * @return Integer
              */
             public function getLimitResult(){
                    return ( ( $this->getPage() - 1 ) * $this->getLimit() );
             }
      }


Para usar com o banco de dados, vamos fazer o seguinte:
andrey@andrey:~$ mysql -u root -pEnter password: ************
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.41 Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create schema paginator;
Query OK, 1 row affected (0.00 sec)

mysql> use paginator;
Database changed
mysql> create table results( id integer auto_increment , data timestamp , primary key( id ) );
Query OK, 0 rows affected (0.05 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.03 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.01 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> insert into results values ( null , null );
Query OK, 1 row affected (0.00 sec)

mysql> select * from results;
+----+---------------------+
| id | data                |
+----+---------------------+
|  1 | 2011-08-25 21:32:49 |
|  2 | 2011-08-25 21:32:50 |
|  3 | 2011-08-25 21:32:51 |
|  4 | 2011-08-25 21:32:51 |
|  5 | 2011-08-25 21:32:52 |
|  6 | 2011-08-25 21:33:00 |
|  7 | 2011-08-25 21:33:00 |
|  8 | 2011-08-25 21:33:01 |
|  9 | 2011-08-25 21:33:11 |
| 10 | 2011-08-25 21:33:12 |
+----+---------------------+
10 rows in set (0.00 sec)

mysql>


Ok, temos dez registros gravados no banco de dados, então, paginando esses resultados com o código postado acima ( PHP ) , seria assim:
<?php

      $PDO = new PDO( 'mysql:host=127.0.0.1;dbname=paginator' , 'root' , '?' );
      $query = $PDO->query( 'SELECT COUNT(*) as `total` FROM `results`' )->fetch( PDO::FETCH_ASSOC );
      /**
       * Recupero o total de resultados retornados na consulta
       */
      $Paginator = new Paginator( $query[ 'total' ] );
      /**
       * Então, seto o 'limite' de resultados por página, seto a página atual
       * e Faço a navegação, gerando os links 
       */
      $Paginator->setLimit( 2 )->setPage( $_REQUEST[ 'p' ] )->renderNavigation( 'Paginator.php' , 'p' );
      $query = $PDO->query( sprintf( 'SELECT * FROM `results` LIMIT %d,%d' , $Paginator->getLimitResult() , $Paginator->getLimit() ) );
      /**
       * Apenas para mostrar os dados da navegação
       */
      printf( 'Registros: %d, Registros Por Página: %d, Página atual: %d, Anterior: %d , Próxima: %d <br />' , 
      $Paginator->getAmount() , $Paginator->getLimit() , $Paginator->getPage() , $Paginator->getPreviousPage() , $Paginator->getNextPage() );
      
      foreach ( $query->fetchAll( PDO::FETCH_ASSOC ) as $Result ) {
             printf( '%d | %s <br />' , $Result[ 'id' ] , $Result[ 'data' ] );
      }


Saída:
<a href="Paginator.php?p=1">1</a>
<a href="Paginator.php?p=2">2</a>
<a href="Paginator.php?p=3">3</a>
<a href="Paginator.php?p=4">4</a>
<a href="Paginator.php?p=5">5</a>

Registros: 10, Registros Por Página: 2, Página atual: 1, Anterior: 0 , Próxima: 2 
1 | 2011-08-25 21:32:49 
2 | 2011-08-25 21:32:50 


Paginando os dados de um Array:
 <?php
      $Array = Array ( 'Item 1' , 'Item 2' , 'Item 3' , 'Item 4' , 'Item 5' , 'Item 6' , 'Item 7' , 'Item 8' );
      $Paginator = new Paginator( sizeOf( $Array ) );
      $Paginator->setLimit( 4 )->setPage( $_REQUEST[ 'pagina' ] )->renderNavigation( 'Paginator.php' , 'pagina' );
      printf( 'Registros: %d, Registros Por Página: %d, Página atual: %d, Anterior: %d , Próxima: %d <br />' , 
      $Paginator->getAmount() , $Paginator->getLimit() , $Paginator->getPage() , $Paginator->getPreviousPage() , $Paginator->getNextPage() );
      foreach( new LimitIterator( new ArrayIterator( $Array ) , $Paginator->getLimitResult() , $Paginator->getLimit() ) as $Item ) {
             echo $Item , '\n';
      }


Saída:
<a href="Paginator.php?pagina=1">1</a>
<a href="Paginator.php?pagina=2">2</a>
Registros: 8, Registros Por Página: 4, Página atual: 1, Anterior: 0 , Próxima: 2 <br />
Item 1
Item 2
Item 3
Item 4

0 comentários:

Postar um comentário

Share

Twitter Delicious Facebook Digg Stumbleupon Favorites More