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