Paginação de resultados/links com PHP
outubro 22nd, 2008 | by DragaO~ |olá pessoas :D
cah estou eu novamente trazendo mais um artigo/tutorial/etc neste blog :D
ha algum tempo eu jah vinha pensando sobre paginaçao de resultados com php, mas nao tinha muita certeza se seria legal postar sobre o assunto
foi entao que o colega Claiton Padilha me deu a ideia de faze-lo, entao, cah estou :D
admito que, antes de realizar este artigo, a paginaçao de resultados era algo meio “obscuro” para mim, sempre tive medo de fazer isso (acreditem, sempre que meu chefe me pedia pra fazer paginaçao eu dava um jeito de passar para outro XD)
bom, sem mais enrolaçoes, vamos ao que importa ;)
segue o codigo abaixo :
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | <? //onde o banco esta hospedado $host = 'localhost'; //usuario que acessa o banco $usuario = 'root'; //senha do usuario que acessa o banco $senha = ''; //banco (database) que desejamos utilizar $banco = 'banco_teste'; //tabela que queremos selecionar os dados $tabela = 'tabela_teste'; //campo da tabela que desejamos mostrar na tela $campo = "campo_teste"; //abrindo a conexao com o banco de dados $sock = mysql_connect($host, $usuario, $senha); //selecionando o banco que iremos utilizar mysql_select_db($banco, $sock); //aqui definimos quantos registros queremos mostrar por pagina $mostrar = 10; //contando o total de registros existente ateh o momento $query = "SELECT COUNT(*) AS total FROM ".$tabela; //enviando a consulta pro banco $query = mysql_query($query, $sock); //pegando o retorno do banco $total = mysql_fetch_array($query); //armazenando o total de paginas $total_paginas = ceil($total['total'] / $mostrar); //tirando a possibilidade de alguem fazer sql injection pela nossa variavel $pagina_atual = htmlentities($_GET['pagina'], ENT_QUOTES); //validando a pagina atual if($pagina_atual > 0 && is_numeric($pagina_atual) && $pagina_atual <= $total_paginas) { $pagina_atual = (int) $pagina_atual; } else { $pagina_atual = 1; } //criando o calculo que nos dira qual vai ser o primeiro registro if($pagina_atual != 1) { $inicio_registros = ($pagina_atual * $mostrar) - ($mostrar); } else { $inicio_registros = 0; } //criando a query (consulta) para mostrar os registros da pagina em questao $query = "SELECT * FROM ".$tabela." LIMIT ".$inicio_registros.", ".$mostrar; //mandando a query (consulta) para o banco $query = mysql_query($query, $sock); //criando uma saida qualquer apenas para exibir os dados ?> <table> <? //mostrando os dados while($dados = mysql_fetch_array($query)) { ?> <tr> <td> <?= $dados[$campo] ?> </tr> </tr> <? } ?> <tr> <td> <? //montando os links no rodape da pagina if($pagina_atual > 1) { ?> <a href="?pagina=<?= $pagina_atual-1 ?>"> < </a> <? } for(; $cont <= $total_paginas; $cont++) { ?> <a <?= ($cont == $pagina_atual) ? " style=\"font-weight: bold;\" " : "" ?> href="?pagina=<?= $cont ?>"> <?= $cont ?> </a> <? } if($pagina_atual < $total_paginas) { ?> <a href="?pagina=<?= $pagina_atual+1 ?>"> > </a> <? } ?> </td> </tr> </table> |
vale lembrar que o foco deste artigo/tutorial nao eh o HTML ou CSS, e sim exclusivamente o PHP (caso notem que tem mais do que simples PHP no codigo :D)
bom, o codigo jah possui alguns comentarios mais “basicos”, agora detalharei cada linha dele ;)
2 3 4 5 6 7 | //onde o banco esta hospedado $host = 'localhost'; //usuario que acessa o banco $usuario = 'root'; //senha do usuario que acessa o banco $senha = ''; |
aqui nestas linhas estamos apenas setando algumas variaveis para nao ter que ficar digitando, e tambem para ficar mais facil de entender o codigo ;D
creio nao necessitar de explicacao, pois elas sao auto-explicativas (e ainda tem os comentarios no codigo neh ;D)
9 10 11 12 13 14 | //banco (database) que desejamos utilizar $banco = 'banco_teste'; //tabela que queremos selecionar os dados $tabela = 'tabela_teste'; //campo da tabela que desejamos mostrar na tela $campo = "campo_teste"; |
aqui continuamos setando algumas variaveis que eu achei comodo setar para este exemplo, logicamente voce nao vai apenas mostrar um campo da tabela como eu estou fazendo aqui :D
16 17 18 19 | //abrindo a conexao com o banco de dados $sock = mysql_connect($host, $usuario, $senha); //selecionando o banco que iremos utilizar mysql_select_db($banco, $sock); |
ufa, estamos quase chegando no que interessa :D
21 22 | //aqui definimos quantos registros queremos mostrar por pagina $mostrar = 10; |
agora sim começou o que importa ;)
à variavel “$mostrar”, damos o valor de quantos registros por paginas nós queremos mostrar, bem simples
23 24 | //contando o total de registros existente ateh o momento $query = "SELECT COUNT(*) AS total FROM ".$tabela; |
aqui estamos criando uma query e atribuindo-a à uma variavel
esta query vai ser responsavel por nos “dizer” quantos registros a nossa tabela possui
25 26 27 28 29 30 | //enviando a consulta pro banco $query = mysql_query($query, $sock); //pegando o retorno do banco $total = mysql_fetch_array($query); //armazenando o total de paginas $total_paginas = ceil($total['total'] / $mostrar); |
aqui enviamos a consulta para o banco, pegamos o resultado dela e armazenamos em uma variavel
notem a ultima linha : pegamos o nosso total de registros (”$total['total']“) e divimos pela quantidade que queremos mostrar em cada pagina, e executamos a funçao “ceil()” (caso nao saiba o que a funçao faça, leia o link para entender, e prossiga com a leitura) à este resultado, para depois atribuir-mos à uma variavel
e eis que temos o total de paginas que nossa consulta vai ter :D
porque utilizamos a funçao “ceil()“? eh muito simples, caso nosso resultado seja um numero exato como “2″, “10″, “34″, etc; nao teremos problemas, mas e com um numero como “3 paginas e meia” (3.5) ?
nao podemos simplesmente deixar meia pagina de fora, e nem realizar uma query começando no registro “3 e meio”, por isso arredondamos o numero para cima utilizando a funçao “ceil()”
no exemplo do “3.5″ o retorno seria “4″, para “2.3″ o retorna ficaria “3″, e assim por diante ;)
32 33 | //tirando a possibilidade de alguem fazer sql injection pela nossa variavel $pagina_atual = htmlentities($_GET['pagina'], ENT_QUOTES); |
nao entrarei em detalhes nesta linha pois seria abordar segurança (talvez em um post futuro ;D)
mas caso queiram entender o que eu fiz aqui, basta ler a documentaçao da funçao htmlentities()
comentario besta : eu uso em 100% dos meus scripts nas quais possuem qualquer tipo de entrada de dados ;D
35 36 37 38 39 40 41 42 | if($pagina_atual > 0 && is_numeric($pagina_atual) && $pagina_atual <= $total_paginas) { $pagina_atual = (int) $pagina_atual; } else { $pagina_atual = 1; } |
tah começando a ficar interessante XD
vamos pensar um pouco :
1 – nao podemos ter paginas negativas
2 – podemos ter apenas paginas numericas (ou esja “1″, “2″, “3″, etc; e nao “a”, “b”, “%$$”, etc)
3 – nao podemos ter mais paginas do que registros
agora vamos ler o if : se a pagina atual for maior que zero e a pagina atual for um numero e a pagina atual for menor ou igual ao total de paginas
perceberam que na linha 37 eu coloquei um “(int)” “inutil” ali ? bem, pois eh, ele nao eh nem um pouco inutil :D
aquele “(int)” ali se chama “cast” (e nao somente ele, todos os tipos de variaveis, estruturas, etc; conhecidos podem fazer isso, exemplo : (int) $variavel, (float) $variavel, (minha_estrutura) $variavel, etc)
o que ele faz eh simplesmente converter uma variavel para o tipo na qual tem nele definido, simples :D
caso tu fizesse
int $variavel;
a variavel “$variavel” seria do tipo int (inteiro) e passaria a aceitar apenas atribuiçoes de numeros inteiros à ela (ok, o php converte automaticamente um tipo para o outro, mas vamos esquecer isso e pensar como acontece no C, por exemplo)
o que eu fiz foi mais uma coisinha de segurança :D
lembra aquele “if” que fazia tres testes ? quais eram os testes que ele fazia ?
exato ;)
agora diga-me, se eu acessar a pagina “3.5″, “3.5″ nao se encaixaria perfeitamente nesse “if” como verdadeiro ? ;)
pois eh, encaixa, porem nao podemos ter paginas “quebradas” (”x.x”), devemos possuir apenas paginas “inteiras” eh eh isso que aquele cast ali faz : pega o resultado do calculo e transforma-o em um numero inteiro, descartando o que vem depois da virgula/ponto ;D
e caso a variavel “$pagina” nao se encaixe nos requisitos, o usuario vai apenas ver a primeira pagina da listagem ;)
44 45 46 47 48 49 50 51 52 | //criando o calculo que nos dira qual vai ser o primeiro registro if($pagina_atual != 1) { $inicio_registros = ($pagina_atual * $mostrar) - ($mostrar); } else { $inicio_registros = 0; } |
chegando neste ponto do codigo, nossa variavel “$pagina” certamente vai ter um valor numerico valido, ou “1″
acontece que, se a pagina for “1″, nos devemos começar no primeiro registro, se nao for a primeira pagina, devemos mostrar, caso a pagina seja 2, por exemplo, os registros “10″ ateh o registro “19″ (lembre-se, os registros começaram em “0″ (zero), se for a pagina “3″, devemos mostrar os registros “20″ ao registro “29″, e assim por diante
como eu nao consegui chegar à um calculo que “incluisse” a possibilidade de pagina “1″, fiz este “if” (caso alguem tenha uma ideia melhor e que funcione igual, sinta-se à vontade para dizer e/ou melhorar :D)
o nosso calculo baseia-se no seguinte :
vamos pegar o “2″ como exemplo, ok ? ;)
como eu posso chegar à “10″ (inicio dos resultados que queremos mostrar (lembre-se, os registros começaram em “0″ (zero)) tendo um “2″ (numero da pagina) e um “10″ (total de registros que vamos mostrar por pagina) ?
eu pensei na seguinte maneira (lembrem-se, existem outras) :
(2 x 10) - (10) (20) - (10) 10
mas o calculo deve servir para ter um “3″ (pagina que estamos mostrando) um “10″ (total de registros que queremos mostrar) para chegarmos em um “20″ (inicio dos registros que vamos mostrar)
(3 x 10) - (10) (30) - (10) 20
opa, serviu ;)
agora colocando na nossa programaçao, temos o codigo acima :
44 45 46 47 48 49 50 51 52 | //criando o calculo que nos dira qual vai ser o primeiro registro if($pagina_atual != 1) { $inicio_registros = ($pagina_atual * $mostrar) - ($mostrar); } else { $inicio_registros = 0,; } |
agora, seguindo adiante…
54 55 | //criando a query (consulta) para mostrar os registros da pagina em questao $query = "SELECT * FROM ".$tabela." LIMIT ".$inicio_registros.", ".$mostrar; |
aqui esta a linha “magica” :D
eh bem simples, acreditem XD
esse comando sql diz :
simples nao ? :D
acho que nao tem mais o que explicar sobre essa linha, mas em caso de duvidas, pergunte ;D
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | //criando uma saida qualquer apenas para exibir os dados ?> <table> <? //mostrando os dados while($dados = mysql_fetch_array($query)) { ?> <tr> <td> <?= $dados[$campo] ?> </tr> </tr> <? } ?> |
aqui estamos mostrando o conteudo do nosso campo especificado no inicio do codigo, acho que nao tem nenhuma novidade ai nao eh ? ;)
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | <tr> <td> <? //montando os links no rodape da pagina if($pagina_atual > 1) { ?> <a href="?pagina=<?= $pagina_atual-1 ?>"> < </a> <? } for(; $cont <= $total_paginas; $cont++) { ?> <a <?= ($cont == $pagina_atual) ? " style=\"font-weight: bold;\" " : "" ?> href="?pagina=<?= $cont ?>"> <?= $cont ?> </a> <? } if($pagina_atual < $total_paginas) { ?> <a href="?pagina=<?= $pagina_atual+1 ?>"> > </a> <? } ?> </td> </tr> |
aqui estamos montando os links que irao fazer a navegaçao pela nossa pagina ^^
primeiro :
caso a pagina nao seja a primeira, deve existir a opçao de voltar uma pagina atras
segundo :
todas paginas devem possuir a possibilidade da pessoa “pular” para qualquer pagina à qualquer momento
notem que essa parte eu apenas coloquei em negrito caso seja a pagina atual, apenas para dar um destaque, mas o layout final eh com voces, pois este tutorial/artigo nao aborda isso ;)
terceiro :
se a pessoa nao estiver na ultima pagina, ela sempre tem a opçao de ir uma pagina adiante da atual
logicamente poderiam ter sido feitas paginas “inicio” e “fim” (aquelas famosas “setas duplas” (”<<" e ">>”))
105 | </table> |
e aqui finalmente fechamos a nossa tabela e terminamos o nosso script ;)
pois eh, o post acabou ficando muito grande…XD
mas espero que tenham curtido ler ele ateh o final, e que tenham aprendido e tirado algumas duvidas com este post ;)
pois eu fui pesquisar para ver como tava a qualidade dos artigos/tutoriais sobre o assunto, e realmente me decepcionei um pouco XD
bom, espero que tenham gostado :D
comentarios/sugestoes sao sempre bem vindos ^^
referencias das funçoes :
mysql_connect(), mysql_select_db(), mysql_query(), mysql_fetch_array(), ceil(), htmlentities(), is_numeric()
ateh o proximo post :D
12 Responses to “Paginação de resultados/links com PHP”
By Claiton Padilha on out 23, 2008 | Reply
Muito Bom o Artigo!!
Eu tenho uma paginação muito mais complicada.
Mas acho que vou começar a usar a “tua”…
eauheue
Só uma observação
essa linha:
$query = “SELECT * FROM “.$tabela.” LIMIT”.$inicio_registros.”, “.$mostrar;
No PostgreSql tem uma pequena diferença
seria assim:
$query = “SELECT * FROM “.$tabela.” LIMIT “.$inicio_registros.” OFFSET “.$mostrar;
Tem o OFFSET, no resto seria igual.
FLw!
E Parabéns!
Quote
By Rafael Diniz on out 25, 2008 | Reply
Não funcionou aqui. Salvei em .php e mesmo assim não deu, criei as tabelas do BD e etc… e não funcionou. Apresentou erros na linha 86 e na 33.
O que será?
Quote
By DragaO~ on out 26, 2008 | Reply
Rafael Diniz,
primeiramente, obrigado pelo comentario :D
por favor, poste o codigo completo que tu tens e tambem os erros exatos que estao aparecendo para ti ;)
bom, caso o codigo esteja EXATAMENTE igual ao meu, inclusive nos comentarios, um possivel erro da linha 33 é que tu não tenha a váriavel do tipo get “pagina” (o que, na verdade, geraria um “warning” (aviso) e nao um “fatal error” (erro fatal))
quanto à linha 86, se teu código estiver igual ao meu, nao vejo uma possibilidade de “fatal error” (erro fatal), apenas de “warning” (aviso), por isso reforço a idéia de tu postar teu codigo exatamente como tu tem, para que eu possa ver exatamente onde está o teu problema
e aconselho tambem, mesmo que não seja muito necessário, postar a estrutura da tua tabela ;)
Quote
By Rafael Diniz on out 31, 2008 | Reply
Erro
“Notice: Undefined variable: cont in C:\Arquivos de programas\EasyPHP 2.0b1\www\Tutos\index.php on line 86
href=”">
Notice: Undefined variable: cont in C:\Arquivos de programas\EasyPHP 2.0b1\www\Tutos\index.php on line 86″
________
código PHP:
0 && is_numeric($pagina_atual) && $pagina_atual
1)
{
?>
<
<?php
}
for(; $cont
<a href=”">
<?php
}
if($pagina_atual
>
___________
se puder me ajudar… curti seu blog em… =)
Quote
By Rafael Diniz on out 31, 2008 | Reply
affff… num dá pra copiar e colar o código completo… seu blog tem um limite…
Quote
By Rafael Diniz on out 31, 2008 | Reply
<?php
}
“linha 86:” for(; $cont
Quote
By Rafael Diniz on out 31, 2008 | Reply
seu blog não suporta mesmo… =/ tem msn mano?
Quote
By DragaO~ on out 31, 2008 | Reply
Rafael Diniz,
imagine que desastre seria se o Wordpress aceitasse e interpretasse tags e comandos PHP, seria o fim dos blogs :D
bom, eu andei testando e o wordpress aceita sim (meu blog eh feito em wordpress), basta tu colocar as tags necessarias antes do teu codigo, assim :
<pre lang=”php” line=”1″>
todo teu codigo php aqui
</pre>
aí a gente vai ver algo assim :
peço-lhes que poste novamente teu código para que eu possa dar uma olhada
sobre aos erros, eles são apenas “warnings” (avisos), não são exatamente “fatal error” (erro fatal)
sobre o limite, eu verifiquei as tabelas do wordpress e ele aceita até 65 mil caracteres por comentário, portanto, limite não é problema ^^
(ao menos nesse caso, lógico)
bpm, desculpe pelo inconveniente :S
Quote
By Jefferson on jan 6, 2009 | Reply
Para que server este sinal de igual – (<?= $dados[$campo)- depois do
Explicando melhor:
Só aparece o cabeçalho com os nomes de data inclusao, titulo, on line, off line, editar
, ai vem o espaço do ; e ai vem a sequencia(número da pagina para paginação) das páginas.
Se puder me ajudar obrigado. Jefferson(iniciante).
Quote
By DragaO~ on jan 6, 2009 | Reply
Esse sinal de igual após a abertura da tag PHP, informa que eu estou querendo “ecoar” o valor da variável (ou string) que vem a seguir
ou seja, fazer isso :
é o mesmo que fazer
ou até mesmo
acontece que, caso a tua diretiva “short_open_tag” esteja desabilitada no php.ini, a única forma de fazer isso é seguindo o terceiro modo, os outros dois anteriores servem apenas se a diretiva “short_open_tag” estivar ligada (ou seja, tiver o valor “on”)
para não ter problemas quanto à isso, já que tu está iniciando, aconselho a usar o terceiro modo (a não ser que tu saiba configurar o php.ini, claro)
peço também, adicionalmente, que se fores postar algum código php, utilize a seguinte sintaxe :
<pre lang=”php”>
//seu codigo php aqui
</pre>
que ele aparecerá assim :
//seu codigo php aquiespero que entenda, pois essa é uma limitação do wordpress (se souber de algum plugin que ajude com isso serei grato)
Obrigado pelo comentário, e em caso de dúvidas, pergunte que eu tentarei ajudar :D
Quote
By cjr_ssa (cleber jr) on mar 3, 2009 | Reply
muito bom esse artigo sobre páginação, venho por meio de vc mesmo que me indicou lá no Gdh em um tópico que criei e me ajudou muito…
muito interresante esse estilo de página e muito simples também pois vc além de comentar nos códigos, comenta passo-a-passo!!!!!
cleber junior
Quote
By DragaO~ on mar 4, 2009 | Reply
Obrigado pelo elogio :)
Tento sempre manter o nível dos posts, comentando-os e dando o maior número de informações possíveis sobre o assunto
Já que gostou, espero que eu o veja por aqui mais vezes :)
Quote