Paginação de resultados com PHP e MySQL

Amostra de técnica de paginação, para mostrar em diferentes páginas os resultados de uma consulta à base de dados. O exemplo está desenvolvido em PHP e MySQL.

Por Miguel Angel Alvarez - Tradução de JML


Publicado em: 29/9/04
Valorize este artigo:
Em muitas ocasiões, quando se apresentam numa página web registos de uma base de dados, deveriam-se mostrar demasiados registos como para colocá-los todos numa única página. Nestas ocasiões costumasse paginar os resultados, talvez centenas, em diferentes páginas com conjuntos de registos muito menos numerosos. Por exemplo, poderíamos apresentar os resultados em páginas de 10 elementos ou 20, dependendo do que queremos fazer e do tipo de dados que se estejam a visualizar. Este efeito podemos observa-lo inúmeras vezes nos portais mais representativos.

Poderíamos desenvolver diversos scrips para paginar resultados em PHP. Neste artigo vamos explicar uma possibilidade baseada na utilização de uma base de dados MySQL e sentenças SQL as que indicaremos o conjunto de registos que queremos mostrar em cada página. Os comandos SELECT da linguagem SQL, na base de dados MySQL e muitas outras, têm uma clausula chamada LIMIT, com a que podemos indicar os registos a mostrar, por exemplo, 10 registos começando pelo registo 180.

select * from pais limit 180,10

Como vemos LIMIT tem dois argumentos, o primeiro indica-nos por onde começar os resultados e o segundo o número de resultados a seleccionar no conjunto de registos resultantes.

Deste modo, neste exercício de paginação a clausula LIMIT será a chave para mostrar os registos em grupos do tamanho desejado.

Podemos ver o resultado que vamos obter neste artigo agora e assim teremos mais facilidade para identificar as diferentes partes de código que vamos ver.

Código de paginação

Existem varias partes do código que servirão especificamente para implementar a paginação. O primeiro é saber qual é a página que se deseja mostrar. Em principio mostraria-se a primeira página de resultados, mas se um visitante selecciona com os links de baixo outra página diferente da primeira, teríamos de a mostrar também. O índice da página a mostrar, se não for a primeira vez que se acede, recebe-se por parâmetro na URL.

//Limito a busqueda
$TAMANHO_PAGINA = 10;

//examino a página a mostrar e o inicio do registo a mostrar
$pagina = $_GET["pagina"];
if (!$pagina) {
   $inicio = 0;
   $pagina=1;
}
else {
   $inicio = ($pagina - 1) * $TAMANHO_PAGINA;
}


Estou a definir o tamanho da página. A seguir tento receber a página por parâmetro na URL. Se não se recebeu nada, entende-se que a página a ser mostrada é a primeira, e a variável &inicio, que guarda o primeiro registo a mostrar (para indica-lo na sentença SQL), será zero. Se tínhamos recebido algo como página, calculo o inicio com uma simples multiplicação da página a mostrar vezes o tamanho de página definido antes.

É habitual nestas páginas de resultados informar um pouco sobre a quantidade de registos encontrados e os dados da página que estamos a ver. Estes dados podem-se obter com umas poucas contas.

//vejo o número total de campos que há na tabela com essa busqueda
$ssql = "select * from pais " . $criterio;
$rs = mysql_query($ssql,$conn);
$num_total_registos = mysql_num_rows($rs);
//calculo o total de páginas
$total_paginas = ceil($num_total_registos / $TAMANHO_PAGINA);

//ponho o número de registos total, o tamanho de página e a página que se mostra
echo "Número de registos encontrados: " . $num_total_registos . "<br>";
echo "Mostram-se páginas de " . $TAMANO_PAGINA . " registos cada uma<br>";
echo "A mostrar a página " . $pagina . " de " . $total_paginas . "<p>";


Nota: Este código poderia mostrar uma informação como esta: Número de registos encontrados: 256 Mostram-se páginas de 10 regisros cada uma A mostrar a página 19 de 26

O primeiro a fazer é uma busqueda na base de dados com o critério que se esteja a utilizar para saber quantos registos se obtêm em total sem a paginação (a seguir veremos de onde obtemos a variável $critério).

A continuação posso calcular o número total de páginas de resultados para gerar a busqueda. A função ceil() aproxima números em virgula flutuante ou reais para cima, isto é, retorna o inteiro por cima mais próximo.

As seguintes linhas, onde se utiliza echo, têm como objetivo mostrar os dados na página.

Agora veremos o código que realiza a búsqueda na base de dados, extraindo e mostrando só aqueles registos que correspondem com a página a mostrar.

//construo a sentença SQL
$ssql = "select * from pais " . $criterio . " limit " . $inicio . "," . $TAMANHO_PAGINA;
$rs = mysql_query($ssql);
while ($fila = mysql_fetch_object($rs)){
   echo $fila->nome_pais . "<br>";
}
//fechamos o conjunto de resultado e a conexão com a base de dados
mysql_free_result($rs);
mysql_close($conn);


Constroi-se a sentença SQL para obter os dados com o critério, que veremos mais tarde de onde se obtém, mas que em principio podemos toma-la como uma cadeia vazia. Também se utiliza LIMIT, como já se indicou: ponde os valores definidos antes como inicio e tamanho de página.

O resto é um recorrido típico através de um conjunto de registos, neste caso os países da nossa base de dados, onde se vão mostrando todos os elementos desde o principio até ao fim. Finalizado este recorrido não vamos realizar mais nenhuma acção com a base de dados, pelo qual podemos fechar o resultado da busqueda e a conexão com a base de dados.

Agora podemos ver o código que mostra a parte de baixo os números de todas as páginas que são geradas pela busqueda, para que o visitante possa seleccionar uma página e mover-se entre os resultados.

//mostro os diferentes índices das páginas, se é que há várias páginas
if ($total_paginas > 1){
   for ($i=1;$i<=$total_paginas;$i++){
      if ($pagina == $i)
         //se mostro o índice da página actual, não coloco link
         echo $pagina . " ";
      else
         //se o índice não corresponde com a página mostrada actualmente, coloco o link para ir a essa página
         echo "<a href='index.php?pagina=" . $i . "&criterio=" . $txt_criterio . "'>" . $i . "</a> ";
   }
}


A primeira linha verifica se realmente há várias páginas de resultados, se assim não for, não mostra nada. Se efectivamente há várias páginas para mostrar recorrem-se todas e para cada uma delas mostra-se o índice.

O índice a mostrar pode que seja o da página que se está a visualizar nesse momento e nesse caso simplesmente pomos o numero, mas não o link para ir a esse documento, pois já estamos nele. No caso de que seja uma página de resultados diferente, mostra-se um link para ir a essa página, onde se inclui passando por parâmetro tanto o índice da página que se deseja ver como o critério da busca que se estava a realizar.

Até aqui temos o código imprescindível para a paginação, mas ainda vamos ver mais alguma coisa.

Código de busca

Para fazer um workshop um pouco mais complete e poder oferecer uma página de amostra com funcionalidades de busca, criámos a possibilidade de acrescentar um critério para encontrar só elementos relacionados com ele. Para além do mais, os códigos de paginação costumam utilizar-se em situações nas que se estão a realizar buscas em bases de dados.

O critério poderá ser definido numa caixa de texto e teremos um botão de procurar que chame à mesma página mas passando o texto com as palavras a ser procuradas na base de dados.

<form action="index.php" method="get">
Criterio de búsqueda:
<input type="text" name="criterio" size="22" maxlength="150">
<input type="submit" value="Buscar">
</form>


Reparamos que o método pelo que passámos este formulário é GET. Isto porque não queremos complicar o código e como estamos a utilizar GET noutros sítios, utilizamos o mesmo método.

Colocamos o formulário debaixo, mas haverá também um bocado de código que recolherá a informação e a tratará para adapta-la a uma sentença de busca na base de dados. Colocaremos este código na parte de cima da página.

//inicio o critério e recebo qualquer cadeia que se deseje procurar
$criterio = "";
if ($_GET["criterio"]!=""){
   $txt_criterio = $_GET["criterio"];
   $criterio = " where nome_pais like '%" . $txt_criterio . "%'";
}


Inicia-se o critério com uma cadeia vazia e depois verificamos se se recebeu algo pelo método GET no campo critério. Em caso afirmativo podemos recolher o texto recebido e construir o critério, que é uma clausula WHERE onde se procuram os elementos, neste caso paises, cujo nome contenham por algum sitio as letras que se receberam como texto do critério.

Base de dados

Tal e como dissemos, está-se a utilizar uma base de dados MySQL. No Manual de programação em PHP de CriarWeb.com mostra-se a maneira de trabalhar com bases de dados.

No nosso exemplo falta-nos por indicar as sentenças para conectar com MySQL e seleccionar a base de dados a utilizar. Seriam umas parecidas a estas.

//conecto com a base de dados
$conn = mysql_connect("servidor","usuario","password");
mysql_select_db("nome_bbdd",$conn);


Pode-se ver aqui o exemplo em funcionamento.

Para aqueles que quiserem esclarecer melhor o método de paginação, o código completo deste exercício é o seguinte:

<form action="pag_php_mysql_ex.php" method="get">
Criterio de busca:
<input type="text" name="criterio" size="22" maxlength="150">
<input type="submit" value="Buscar">
</form>
<?
//inicio o critério e recebo qualquer cadeia que se deseje procurar
$criterio = "";
if ($_GET["criterio"]!=""){
    $txt_criterio = $_GET["criterio"];
    $criterio = " where nome_pais like '%" . $txt_criterio . "%'";
}
//conecto com a base de dados
$conn = mysql_connect("servidor","usuario","password");
mysql_select_db("nome_bbdd",$conn);
//Limito a busca
$TAMANHO_PAGINA = 10;
//examino a página a mostrar e o inicio do registro a mostrar
$pagina = $_GET["pagina"];
if (!$pagina) {
    $inicio = 0;
    $pagina=1;
}
else {
    $inicio = ($pagina - 1) * $TAMANHO_PAGINA;
}
//vejo o número total de campos que há na tabela com essa busca
$ssql = "select * from pais " . $criterio;
echo "

$ssql</p>";
$rs = mysql_query($ssql,$conn);
$num_total_registos = mysql_num_rows($rs);
//calculo o total de páginas
$total_paginas = ceil($num_total_registos / $TAMANHO_PAGINA);
//ponho o número de registros total, o tamanho de página e a página que se mostra
echo "Número de registros encontrados: " . $num_total_registros . "<br>";
echo "Mostram-se páginas de " . $TAMANHO_PAGINA . " registros cada uma<br>";
echo "A mostrar a página " . $pagina . " de " . $total_paginas . "<p>";
//construo a sentença SQL
$ssql = "select * from pais " . $criterio . " limit " . $inicio . "," . $TAMANHO_PAGINA;
$rs = mysql_query($ssql);
while ($fila = mysql_fetch_object($rs)){
    echo $fila->nome_pais . "<br>";
}
//fechamos o conjunto de resultado e a conexão com a base de dados
mysql_free_result($rs);
mysql_close($conn);
//mostro os diferentes índices das páginas, se é que há várias páginas
if ($total_paginas> 1){
    for ($i=1;$i<=$total_paginas;$i++){
       if ($pagina == $i)
          //se mostro o índice da página atual, não coloco link
          echo $pagina . " ";
       else
          //se o índice não corresponde com a página mostrada atualmente, coloco o link para ir a essa página
          echo "<a href='pag_php_mysql_ex.php?pagina=" . $i . "&criterio=" . $txt_criterio . "'>" . $i . "</a> ";
    }
}
?>





Comentários do artigo
Foram enviados 25 comentários ao artigo
12 comentários não revisados
13 comentários revisados:
Por: Anderson
06/11/06
Otimo artigo...
Estou a tempos procurando um artigo com esse nível de explicação...Ate que enfim achei..muito bom mesmo...
Ate acrescentei "Proxima" pagina e "Anterior" pagina, e no $criterio fiz um order by de acordoo com o escolhido...
Muito facil depois de entender a logica...

Vlw..
Por: Fernanda
26/12/06
Quando clico em algum link de páginas, ele dá erro.
No meu caso retornou 10 páginas, e quando clico ou consulto algum nome, dá erro.
Poderia dar um help??
Obrigado
Por: Areshandore
13/4/07
Fernanda, acho que a essa altura você já deve estar craque em paginação, mas se for o caso de você ainda não ter aprendido, talvez um detalhe que eu estava me confundindo seja também o seu problema ou de outras pessoas:

Tem-se que fazer 2 consultas, uma pra saber quantos resultados são no total e outra usando limit pra mostrar os resultados referentes a uma(1) página.
Por: Areshandore
13/4/07
Ah Fernanda, erro no link pode ser porque talvez você tenha esquecido de dar uma olhada na última linha, olha só:
<a href='pag_php_mysql_ex.php?pagina=" . $i . "&criterio=" . $txt_criterio . "'>" . $i . "</a>

Se o nome do seu php não for é pag_php_mysql_ex.php com certeza vai dar erro... :)
Por: Areshandore
13/4/07
Desculpe comentar tantas vezes, essa é a última... rs. Gostei muito do artigo e é como o Anderson falow, fica fácil depois que se aprende a lógica. É por esse e outros artigos como esse que eu sou fã desse site. :)
Por: Aguinaldo Dalberto
12/5/07
Excelente dica, agora fica mais fácil fazer paginações.
Por: Bernardo
12/11/07
Mto bacana o artigo !!! completissimo e que isso ... mto mto bom mesmo ... consegui utilizar a mesma estrutura e funcionar perfeitamente .... porém estou trabalhando em algumas melhorias do tipo: inclui um LISTBOX com 4 opções de pesquisa as quais possuem como value respectivos (1,2,3,4) dentro da página montei uma estrutura que pega esse valor e se for 1 adiciona ao critério uma condição X e assim para cada uma das opções .... fiz a consulta funcionar e retornar perfeitamente os resultados e tudo mais ..... porém se clico na próxima página ele simplesmente faz uma consulta NULA no banco e retorna todas as páginas..... já tentei trabalhar os calculos dentro das estruturas de verificação das condições passadas pelo listbox mas mesmo assim não está funcionando ...... alguem poderia ajudar ?!?!?

valeuuuuuuuuuu
Por: Bruno
02/1/08
Parabens pelo o script está bastante simples e eficaz. Resulta na prefeição.

Por: Alexandre
29/4/08
Não me aparece o total de registros, Vi que têm uma pequena diferença entre o cod. comentado par por parte e o cod. completo abaixo! um têm echo "$ssql</p>"; e o outro não têm esta linha! Qual o certo? Porque será que o meu não me tráz o total de campo da tabela!
Por: Alan Carvalho
07/9/08
Melhor post de php sobre o assunto.

Através do mesmo consegui criar um método de consulta dos usuários cadastrados c/ paginação em meu sistema .


Obrigado mesmo
Paginação de resultados com PHP e MySQL
Por: hrondeico
15/11/09
O exemplo publicado mostra como é simples controlar paginação de dados em PHP, em contra-partida ASP/VBscript requer mais linhas de programação.

Meus agradecimentos Miguel Alvarez pela matéria. O material publicado foi útil para mim e já aproveitei-o implementando nos meus documentos.
script
Por: srobladen
20/1/10
muuuuuuuuuuuuito bom, ajudou muito
RE: Bernardo
Por: rafaelbordallo
20/1/11
Fera,
Ocorreu a mesma coisa comigo, mas a solução é simples.

EX:

Nos meus critérios, quando busco por eles me gera a seguinte URL:

pagina=1&buscaNome=&buscarSexo=&buscarEstado=RJ

Com essas informações eu montei o link das páginas com a mesma estrutura buscando por GET os resultados da URL:

<a href='lista_cadastro.php?pagina=" . $i . "&buscaNome=".$_GET['buscaNome']."&buscarSexo=".$_GET['buscarSexo']."&buscarEstado=".$_GET['buscarEstado']."'>


Com isso, caso você tenha resultados nos critérios, vão ser enviados para sua próxima página.
Espero ter ajudado!

Abraços

Usuários :    login / registro

Manuais relacionados
Categorias relacionadas
O autor

Home | Sobre nós | Copyright | Anuncie | Entrar em contato