Paginação Avançada Com PHP
Todo website com uma quantidade média a grande de conteúdo precisa paginar o conteúdo. Desta maneira ele fica organizado e possibilita ter uma idéia sobre o conteúdo disponível. O exemplo mais comum são os blogs, mas esta idéia também se aplica ao resultado das buscas e outros websites.
Neste tutorial vou mostrar como criar uma paginação simples, com números seqüenciais, e a avançada onde é possível ter acesso à primeira e última página além do intervalo entre a página atual, próximas e anteriores como você pode conferir na imagem abaixo:

Antes de partirmos para a programação vamos analisar pontos importantes que devem ser observados na criação da paginação.
O Design Da Paginação
Um aspecto muitas vezes negligenciado no design das páginas é a paginação. As vezes ficam aqueles números pequenos mal espaçados difíceis de clicar. Uma experiência terrível para o usuário.
A primeira medida então é oferecer uma área de clicagem generosa para evitar erros e clicar no link do lado. Um bom espaçamento entre os números já resolve o problema, nem precisa aumentar o tamanho da fonte.
E por ser um link, a aparência dele deve mudar quando o mouse passar sobre os números. Estamos na web, interatividade, resposta imediata das ações. Adicionar link para a próxima página e a anterior facilita muito a vida do leitor.
Informe com estilização diferenciada em qual página o usuário encontra-se. Sempre de maneira intuitiva na linha “não me faça pensar”.
Se você gosta de sair do comum e quer criar uma paginação inovadora, cuide com a empolgação e tenha em mente como aspecto principal a usabilidade.
Os Textos
Os textos são inseridos a partir de uma tabela no banco de dados. Neste tutorial utilizei uma tabela chamada ‘artigos’ com os campos para id, titulo e texto e é feita uma conexão com o banco de dados.
<?php
$db = "banco_dados";
@mysql_connect("localhost", "usuario", "senha") or trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db($db);
?>
Como A Paginação Funciona
Com as sentenças SQL você pode delimitar quantos registros são retornados pela busca na tabela. A cláusula LIMIT faz este papel. Para selecionar os registros do 5 ao 10 de uma tabela escreve-se:
SELECT * FROM tabela LIMIT 5,5
O primeiro número indica a partir de qual deve ser feita a seleção, e o último quantos registros entram na conta. Alterando estes valores que conseguiremos apresentar na tela os registros respectivos de cada pagina.
Variáveis Iniciais
A principio precisamos saber qual página pretende-se visualizar e quantos registros serão mostrados por página.
<?php
$pag = ($_GET['pag']);
$pag = filter_var($pag, FILTER_VALIDATE_INT);
$inicio = 0;
$limite = 1;
if ($pag!='')
{
$inicio = ($pag - 1) * $limite;
}
Na primeira linha a variável recebe o número da página e na segunda é feita uma verificação para validar o número. Lembrando que o filter_var somente esta disponível a partir do PHP 5.2.
Os valores padrão para a seleção dos registros são 0 e 1. Por isso as variáveis com os respectivos nomes. Se o número da página não for passado estes é que serão os adotados. Mas se o número da página for diferente de nada, a variável ‘inicio’ vai receber o resultado da subtração deste número por 1 vezes o limite de registros a serem mostrados por página. Qual o propósito do cálculo?
Pense que para mostrar o primeiro registro, na sentença SQL a seleção deve ser feita partindo do número 0 e selecionando um registro:
SELECT * FROM tabela LIMIT 0, 1
Então para selecionar o segundo registro parte do primeiro e seleciona mais um (1+1=2). Se você quiser mostrar dois textos por página, vai bastar alterar o valor da variável ‘limite’ para 2.
Fazendo A Busca E Mostrando O Resultado
Vejamos a aplicação das variáveis setadas. Supondo que é a primeira vez que a página é acessada então são utilizados os valores padrão das variáveis ‘inicio’(0) e ‘limite’(1).
$busca = mysql_query("SELECT * FROM artigos LIMIT $inicio, $limite");
if (mysql_num_rows($busca)>0)
{
while ($texto = mysql_fetch_array($busca))
{
extract($texto);
echo '<h2>'.$titulo.'</h2>';
echo '<p>'. nl2br($artigo).'</p>';
}
}
São selecionadas todas as colunas da tabela artigos limitadas entre o registro 0 e o 1. Isso quer dizer, o primeiro registro. Se a busca retornar algum registro e feito um laço para que, enquanto a variável ‘texto’ receber o retorno da busca os dados são extraídos e mostrados na tela.
Os Números Da Paginação
Vamos configurar os valores para os botões de próximo, anterior e adjacentes da atual página.
$busca_total = mysql_query("SELECT COUNT(*) as total FROM artigos");
$total = mysql_fetch_array($busca_total);
$total = $total['total'];
$prox = $pag + 1;
$ant = $pag - 1;
$ultima_pag = ceil($total / $limite);
$penultima = $ultima_pag - 1;
$adjacentes = 2;
Nas primeiras três linhas é feita uma busca que retorna o número de registros da tabela, os dados são transformados em matriz e o número total é atribuído para a variável ‘total’.
Os links para a próxima página e a anterior terão como valores o número atual da página acrescido ou decrescido em 1. O valor para o link da última página é o resultado da divisão do total de registros pelo número deles que é mostrado na tela. Com isso tendo 10 registros no total e sendo mostrados 2 por página, o valor da última página será 5. Pegando este valor é subtraído 1 para o valor da penúltima página. A variável ‘adjacentes’ configura quantos números ficarão disponíveis em cada lado da página atual na paginação.
Ficará mais claro o porque destas variáveis conforme formos aplicando no código abaixo.
Paginação Simples
Se o número de registos retornado não for suficiente nem para 5 páginas não precisamos adicionar os números adjacentes nem os pontos para indicar que existem páginas além.
if ($pag>1)
{
$paginacao = '<a href="index.php?pag='.$ant.'">anterior</a>';
}
if ($ultima_pag <= 5)
{
for ($i=1; $i< $ultima_pag+1; $i++)
{
if ($i == $pag)
{
$paginacao .= '<a class="atual" href="index.php?pag='.$i.'">'.$i.'</a>';
} else {
$paginacao .= '<a href="index.php?pag='.$i.'">'.$i.'</a>';
}
}
}
Se o número da página atual é maior do que um, então cabe o link para ver a página anterior. Já estamos aplicando a variável configurada anteriormente no código.
A próxima verificação poderia ser engatada como else da que virá abaixo, mas para deixar o código mais organizado vamos deixá-la sozinha.
Se a última página, que é o resultado da divisão do total de registros pelo número deles que é mostrado em cada página, for menor do que cinco, é feito um laço. Para ‘i’ que recebe um, enquanto ele for menor do que seis (última página + 1), o laço se repete. Nele os links são mostrados com os valores para os respectivos números de página. A verificação é para saber se o ponteiro do laço esta com o mesmo valor que a página atual, que requer uma estilização diferente para informar o usuário onde ele esta.
Observe que os valores estão sendo atribuídos a variável ‘paginacao’, ela ainda vai receber muitos dados no decorrer do código.
Os Intervalos Na Paginação
Se o número de páginas for maior do que cinco, já é possível criar os intervalos.
if ($ultima_pag > 5)
{
if ($pag < 1 + (2 * $adjacentes))
{
for ($i=1; $i< 2 + (2 * $adjacentes); $i++)
{
if ($i == $pag)
{
$paginacao .= '<a class="atual" href="index.php?pag='.$i.'">'.$i.'</a>';
} else {
$paginacao .= '<a href="index.php?pag='.$i.'">'.$i.'</a>';
}
}
$paginacao .= '...';
$paginacao .= '<a href="index.php?pag='.$penultima.'">'.$penultima.'</a>';
$paginacao .= '<a href="index.php?pag='.$ultima_pag.'">'.$ultima_pag.'</a>';
}
elseif($pag > (2 * $adjacentes) && $pag < $ultima_pag - 3)
{
$paginacao .= '<a href="index.php?pag=1">1</a>';
$paginacao .= '<a href="index.php?pag=1">2</a> ... ';
for ($i = $pag-$adjacentes; $i<= $pag + $adjacentes; $i++)
{
if ($i == $pag)
{
$paginacao .= '<a class="atual" href="index.php?pag='.$i.'">'.$i.'</a>';
} else {
$paginacao .= '<a href="index.php?pag='.$i.'">'.$i.'</a>';
}
}
$paginacao .= '...';
$paginacao .= '<a href="index.php?pag='.$penultima.'">'.$penultima.'</a>';
$paginacao .= '<a href="index.php?pag='.$ultima_pag.'">'.$ultima_pag.'</a>';
}
else {
$paginacao .= '<a href="index.php?pag=1">1</a>';
$paginacao .= '<a href="index.php?pag=1">2</a> ... ';
for ($i = $ultima_pag - (4 + (2 * adjacentes)); $i <= $ultima_pag; $i++)
{
if ($i == $pag)
{
$paginacao .= '<a class="atual" href="index.php?pag='.$i.'">'.$i.'</a>';
} else {
$paginacao .= '<a href="index.php?pag='.$i.'">'.$i.'</a>';
}
}
}
}
Se a página atual for menor do que cinco (o adjacentes esta configurado com 2) é feito um laço. No for, enquanto a variável ‘i’ for menor do que seis os números são mostrados fazendo uma verificação para saber qual é a página atual que exige uma estilização diferente.
Gerados os números, à variável ‘paginacao’ ainda são somados os três pontos e a última e penúltima página.
Mas se a página atual for maior do que quatro e menor do que a última menos três, é uma página intermediária. Primeiro são anexadas a primeira e última páginas. Depois é feito um laço para definir as adjacentes.
A variável ‘adjacentes’ recebeu neste código o valor dois. Para enteder melhor este laço vamos supor que estamos na página seis. A variável ‘i’ vai receber quatro (atual – adjacentes), enquanto ela for menor do que oito (atual + adjacentes) os números links gerados com uma verificação para saber qual é a página atual. Por fim são anexadas a última e penúltima páginas.
O último else é para quando a página atual esta perto do final da numeração. São anexadas a primeira e última páginas além dos três pontos. A variável ‘i’ recebe o resultado da última página menos oito (4+2*2) enquanto não for menor ou igual a este número, os links são gerados.
Na Tela
Até esta altura do código, nenhuma paginação foi mostrada, apenas a variável ‘paginacao’ recebeu os links.
if ($prox <= $ultima_pag && $ultima_pag > 2)
{
$paginacao .= '<a href="index.php?pag='.$prox.'">próxima »</a>';
}
echo $paginacao;
echo '</div>';
A variável ainda recebe o link para a próxima página que é atribuído após uma verificação para saber se não estamos na última página nem na primeira.
Por fim com um echo toda a paginação é mostrada e é fechada a div que contém os links.
Download do código utilizado neste tutorial: Paginação Avançada Com PHP
Related posts:






(1 votes, average: 4.00 out of 5)





Olá
Não entendi muito bem, mas vou dar um bela estuda e fazer vários testes localmente.
Fazendo os testes me surgiu o seguinte erro:
Fatal error: Call to undefined function: filter_var() in …\index.php on line 23
Olá! O Maicon, autor do tutorial, vai comentar e explicar. Um Abraço Rui Soares
Olá rdmelo. O filter_var() somente esta disponível no PHP 5.2. Provavelmente foi por isso que você esta encontrando este erro. A versão do seu PHP é anterior. Filtre os dados com outra função, como strip_tags e teste.
De fato usando strip_tags resolvi meu problema inicial. Agora estou com uma dúvida: No meu bd tenho 12 registros, quando eu deixo a $limite = 5 o resultado é uma paginação com 3 links, porém o resultado é apenas 10 registros. Ficou faltando os 2 primeiros registros no bd que são os mais aintigos. Sem contar que alguns registros se repetiram, aparecendo tanto no link 1 quanto no link 2 ou no 3. A minha busca no bd está sendo feita pelo id e ordenado por Desc ficando assim: "select * from testes where status = '1' order by id desc limit $inicio, $limite". Se eu mudar a $limite para 10 o problema persiste. Pergunta: Além de mudar a $limite , preciso mudar outras variaveis para obter uma paginação correta? Você tem ideia do porque os últimos registros não estão aparecendo e porque alguns se repetem?
Olá! Vou pedir ao Maicon para responder. Um Abraço! Rui Soares
tambem tenho esse problema dava bastante jeito saber a resposta a isso! obrigado
Olá Gonçalo! Pedi hoje ao Maicon para ler os vossos comentário e responder. Um Abraço Rui Soares
Olá rdmelo e gonçalo. Revi o código e realmente é preciso fazer uma pequena alteração no cálculo que define a partir de qual registro deve ser feita a seleção na tabela. A variável 'inicio' deve receber o seguinte cálculo:
$inicio = ($pag – 1) * $limite;
A alteração já foi feita no tutorial e peço desculpas por este descuido no código.
Valeu Maicon, não relatei o meu problema, mas era exatamente este. Segui este passo e está tudo certinho agora.
Muito obrigado.
Olá, ótimo tutorial. Queria saber como posso mostrar o número de 5 páginas por exemplo. Queria que o '…' ficasse tipo assim: 1 2 3 4 5 … Proxima>> Isso para as 5 primeiras páginas. Caso a pessoa navegasse até a oitava página por ex. seria: <<Anterior … 4 5 6 7 8 … Proxima >>. No seu exemplo aparece sempre as 2 primeiras páginas: 1 2..4 5 6..10 12 por ex. Grato.
Ótimo tutorial, adorei, proucurei por isso a um tempão.
Só está faltando uma coisa se vcs puderem me ajudar o tuto vai ficar exelente é dar um resultado para busca, por exemplo se eu colocar – FROM usuarios WHERE cliente_nome LIKE '%".$palavra."%' – e o resultado da pesquisa forem 3 itens o primeiro ele me retorna o resultado correto, porem se eu clico no link da paginação para exibir o proximo resultado ele me mostra todos os resultados que estão cadastrado no bd.
Assim! me parece que se por exemplo eu digito no campo de busca bolo, ele me retorna que tem 3 bolos cadastrados mais quando eu clico no link para exibir o broximo bolo o nome bolo some da pesquisa e ele me retorna todos os produtos cadastrados no bd como se eu não tivece digitado um parametro para pesquisa. Se vcs puderem me ajudar ficarei muito agradecido e tenho certeza que ajudarão muitos companheiros que lerem este tuto, valeu!
achei seu tutorial excelente… estou utilizando ele em um projeto mas ta com dois erros que não consigo descobrir o que esta havendo o primeiro seria o mesmo que o Alexandre postou quando coloco algo dentro do LIKE ele tras os resultados mas se tver mais de uma pagina de resultados a proxima pagina aparece em branco, o outro problema é que tenho uma pagina que lista todos os anuncios mas eu passo o valor sem LIKE ai ele mostra todos os resultados em suas devidas pagina mas quando chega na ultima pagina e tem por exemplo 2 resultados de 15 que é pra mostrar ele mostra os 15 resultados repetindo alguns da pagina anterio, como faço pra ele mostrar somente os dois ultimos resultados na pagina…fico no aguardo vlw.
Muito bom amigo este seu código,estou utilizando aqui em um projeto para um cliente, fiz umas pequenas mudanças e ficou da hora.
Baixei o script para estudar ele, e no meu caso está dando estes erros:
Notice: Undefined index: pag in D:wampwwwPAGindex.php on line 22
Notice: Undefined variable: paginacao in D:wampwwwPAGindex.php on line 69
o estranho é que se começo a navegar nas páginas, ele deixa de dar erro. aí se votlo para a primeira ou vou para a última dá o erro novamente.
Amigo, esse seu problema pode ser resolvido colocando um @ antes da variavel, ficando asim: @$paginacao, esse erro aparece, pq na primeira página, a váriavel está vazia, fazendo com que ela fica como sem valor, por isso mostra o erro, já qunado vc navega, ela passa a ter um valor. então pra evitar esse erro, coloque um @ no começo da variavel.
Senhores, o meu erro é o mesmo do colega Adilson. Como faço para resolver???
fantastico, vlw mesmo!!!! god bless you!!!
Perfeito!!! Parabéns!!!
Ola amigo ?
Eu também estou tendo o mesmo problema dos colegas Adilson e Luciano !!
Eu já testei com PHP 5.2.11 e 5.3.0 .
Se puder dar uma ajudinha, fico muito grato !!
Agradeço desde já.
Olá !
Eu consegui resolver o erro que estava dando, igual dos colegas Adilson e Luciano !
É só colocar um ' @ ' antes das variaveis que estiver dando erro ( indefinida ) !
Pra mim deu tudo certo, espero que pra vocês também !
Até mais.
Olá primeiramente gostaria de informar que foi ótimo seu post. Porém estou com a mesma dúvida do júnior.
Quando a página avança das adjacentes, depois dos pontos "…" aparecem todas as páginas do início de volta inclusive uma página de número " -1 ". Gostaria de saber como remover esse suposto erro. No mais parabéns
Legal
Olá a todos, gostaria de informar que na linha:
for ($i = $ultima_pag – (4 + (2 * adjacentes)); $i <= @$ultima_pag; $i++)
está faltando um $ no adjacentes já que é uma variável, então ficando assim:
for ($i = $ultima_pag – (4 + (2 * $adjacentes)); $i <= @$ultima_pag; $i++)
Vi que na paginação que você desenvolveu (muito boa por sinal), a próxima página pega os anteriores e mais um da nova página. Vou explicar: Se eu colocar para paginar 5 registros por página e tiver um total de 6 registros na minha consulta, ele me retornará na segunda página, os quatro da página anterior mais o registro que falta. Como eu faria para que ele pegasse apenas à partir do ponto que falta, ou seja, neste exemplo somente o sexto registro?
Obrigado e parabéns pelo artigo!
esse erro que a maioria está encontrando é apenas um erro de digitacao. encontrem essas linha:
$paginacao .= '1';
$paginacao .= '2 … ';
alterem para:
$paginacao .= '1';
$paginacao .= '2 … ';
Olá amigo, tenho uma dúvida…
Quando altero a variável ' $limite ' para 2 por exemplo, para mostrar 2 artigos por página, o último artigo dessa primeira página, aparece em primeiro na segunda página e assim por diante…
Como faço para corrigir esse problema ?? Desde já agradeço… e parabéns pelo Artigo…