Classe de Paginação com PDO

Já há algum tempo que escolhi o PDO como classe para trabalhar com banco de dados no PHP,

e não por menos encontrei problemas com paginação de resultados.

Num domingo, resolvi criar um código estruturado para paginar um site que desenvolvi em www.himoveis.com.

Então hoje resolvi criar uma classe baseada neste código.

O resultado ficou bem interessante e simples. Este código foi baseado numa necessidade pessoal, por isto você com mais experiência poderá ter uma ideia melhor de como desenvolver o mesmo código.

Não vou explicar os processos de desenvolvimento da classe, apenas vou distribuir o código para que você possa se beneficiar dele. No código fonte deste post há o arquivo SQL contento a tabela com os países usados.

Eu usei somente um arquivo enquanto desenvolvia, você pode modificar este código à vontade e separar as partes em outros arquivos pequenos.

<?php

/*

 * Author	Gilberto Albino

 * License	None

 * Date		2009-03-15

 */

/*

 * Pedimos para o PHP mostrar os erros, caso esteja desativado

 */

error_reporting(E_ALL|E_STRICT);

ini_set('display_errors', 1);

/*

 * Constantes usadas pela classe de conexão, poderia estar num arquivo externo.

 */

 // o dsn é a string para conexão com o PDO que pode variar de banco para banco

 // Por isto, preste atenção que nesta string temos o driver, o host e o banco(dbname)

defined('DSN') or define('DSN', 'mysql:host=localhost;dbname=teste');

defined('USUARIO') or define('USUARIO', 'root');

defined('SENHA') or define('SENHA', '');



echo '<h1>Paginação PDO</h1>';



/*

 * Classe para paginação em PDO

 */

class Paginacao_PDO

{

  public $paginador = 'pag';

  private $solicitador;

  public $sql;

  public $limite = 10;

  public $quantidade = 5;



  // Construtor carrega a string usada para como paginador

  public function __construct()

  {

	$this->solicitador = $_REQUEST["{$this->paginador};

  }

  // Conexão privada

  private function conexao()

  {

	$conexao = new Conexao();

	$con = $conexao->conexao;

	return $con;

  }

  // Retorna o número de resultados encontrados

  public function resultado()

  {

	$this->resultado = $this->conexao()->query(str_replace('*', 'COUNT(*)', $this->sql));

	$this->numeroResultados = $this->resultado->fetchColumn();

	return $this->numeroResultados;

  }

  // Imprime um texto amigável mostrando o status das paginas em relação ao resultado atual

  public function imprimeBarraResultados()

  {

	if($this->resultado() > 0) {

	  echo '<p class="info_resultado_busca">';

	  echo 'Exibindo página <b style="font-size:20px">' . $this->paginaAtual()

	  . '</b> de <b style="font-size:20px">' . $this->paginasTotais()

	  . '</b> disponíveis para <b style="font-size:20px">'

	  . $this->resultado() . '</b> resultados encontrados.</p>';

	} else {

      echo '<p class="info_resultado_busca">Não foram encontrados resultados para sua busca.</p>';

	}

  }

  // Calcula o número total de páginas

  public function paginasTotais()

  {

	$paginasTotais = ceil($this->resultado() / $this->limite);

	return $paginasTotais;

  }

  // Procura o número da página Atual

  public function paginaAtual()

  {

	if (isset($this->solicitador) && is_numeric($this->solicitador)) {

	  $this->paginaAtual = (int) $this->solicitador;

	} else {

      $this->paginaAtual = 1;

	}



	if ($this->paginaAtual > $this->paginasTotais()) {

      $this->paginaAtual = $this->paginasTotais();

	}



	if ($this->paginaAtual < 1) {

      $this->paginaAtual = 1;

	}



	return $this->paginaAtual;

  }

  // Calcula o offset da consulta

  private function offset()

  {

	$offset = ($this->paginaAtual() - 1) * $this->limite;

	return $offset;

  }

  // Retorna o SQL para trabalhar posteriormente

  public function sql()

  {

	$sql = $this->sql .  " LIMIT {$this->limite} OFFSET {$this->offset()} ";

	return $sql;

  }

  // Imprime a barra de navegação da paginaçaõ

  public function imprimeBarraNavegacao()

  {

	if($this->resultado() > 0) {

	  echo '<div id="navegacao_busca">';

      if ($this->paginaAtual() > 1) {

		echo " <a href='?" . $this->paginador . "=1"

		. $this->reconstruiQueryString($this->paginador) . "'>Primeira</a> ";

		$anterior = $this->paginaAtual() - 1;

		echo " <a href='?" . $this->paginador . "=" . $anterior

		. $this->reconstruiQueryString($this->paginador) . "'>Anterior</a> ";

	  }



	  for ($x = ($this->paginaAtual() - $this->quantidade); $x <

	  (($this->paginaAtual() + $this->quantidade) + 1); $x++) {

		if (($x > 0) && ($x <= $this->paginasTotais())) {

		  if ($x == $this->paginaAtual()) {

			echo " [<b>$x</b>] ";

		  } else {

			echo " <a href='?" . $this->paginador . "=" . $x

			. $this->reconstruiQueryString($this->paginador) . "'>$x</a> ";

		  }

		}

	  }



	  if ($this->paginaAtual() != $this->paginasTotais()) {

		$paginaProxima = $this->paginaAtual() + 1;

		echo " <a href='?" . $this->paginador . "=" . $paginaProxima

		. $this->reconstruiQueryString($this->paginador) . "'>Próxima</a> ";

		echo " <a href='?" . $this->paginador . "=" . $this->paginasTotais()

		. $this->reconstruiQueryString($this->paginador) . "'>Última</a> ";

	  }



	  echo '</div>';

	}

  }

  // Monta os valores da Query String novamente

  public function reconstruiQueryString($valoresQueryString) {

	if (!empty($_SERVER['QUERY_STRING'])) {

	  $partes = explode("&", $_SERVER['QUERY_STRING']);

	  $novasPartes = array();

	  foreach ($partes as $val) {

	    if (stristr($val, $valoresQueryString) == false)  {

          array_push($novasPartes, $val);

		}

	  }

	  if (count($novasPartes) != 0) {

		  $queryString = "&".implode("&", $novasPartes);

	  } else {

		return false;

	  }

	  return $queryString; // nova string criada

	} else {

      return false;

	}

  }



}



class Conexao

{

  private $_usuario;

  private $_senha;

  private $_dsn;



  public function __construct()

  {

	$this->defineUsuario(USUARIO);

	$this->defineSenha(SENHA);

	$this->defineDSN(DSN);

	$this->abreConexao();

  }

  // Define o Usuário

  public function defineUsuario($usuario)

  {

	$this->_usuario = $usuario;

  }

  // Define a Senha

  public function defineSenha($senha)

  {

	$this->_senha = $senha;

  }

  // Define o DSN

  public function defineDSN($dns)

  {

	$this->_dsn = $dns;

  }

  // Abre a conexão sem retornar a mesma

  public function abreConexao()

  {

	$this->conexao = new PDO($this->_dsn, $this->_usuario, $this->_senha);

	$this->conexao->query("SET NAMES utf8");

  }

  // Fecha a conexao

  public function fechaConexao()

  {

	$this->_conexao = null;

  }

}



// Para trabalharmos externamente à classe Paginacao_PDO

$conexao = new Conexao();

$conexao = $conexao->conexao;

// Iniciamos a paginacao

$paginacao = new Paginacao_PDO();

$paginacao->sql = "select * from paises";

// Status dos Resultados

$paginacao->imprimeBarraResultados();

// A partir do método sql() de Paginacao_PDO

// Vamos listar os resultados

$res = $conexao->query($paginacao->sql());

while($r = $res->fetch(PDO::FETCH_OBJ)) {

	print $r->nome . "<br />";

}

// Barra de Navegação

$paginacao->imprimeBarraNavegacao();

6 comentários sobre “Classe de Paginação com PDO”

  1. Ol?

    Parab?ns pelo trabalho.

    Eu testei sua clase com uma base que tem 15.000 registros. Resultado:

    Fazendo uma select normal em uma tabela sem problemas. Mas qdo fiz um join com outra tabela o m?todo imprimeBarraResultados() trou as informa??es dobradas em vez de trazer 14.583 registros trouxe 72236 resultados encontrados.

    N?o entendo o porque, at? tentei algumas altera??es mas sem sucesso!

    De qualquer forma valeu, eu estava precisando de uma pagina??o assim.

    Abra?o!

  2. Ent?o F?bio, n?o creio que o problema seja com a classe, uma vez que ela s? faz a pagina??o.
    Entretanto, caso voc? descubra o motivo, gostaria de ficar por dentro de sua descoberta.
    Abra?o…

  3. boas,
    eu utilizei o sistema de pagina??o e funciona muito bem, agora s? tenho uma duvida, se eu quiser fazer um sistema de pesquisa como posso adaptar este c?digo? porque sempre que fa?o a pesquisa e mudo de pagina eu perco a pesquisa e o sistema volta a buscar a query inicial, ha forma de manter a query da pesquisa?

    Desde j? parab?ns pelo trabalho

    Cumprimentos,
    Felipe

  4. Obrigado por disponibilizar esta classe, tem me ajudado bastante.
    No firebird (2.5) fiz as seguintes alterações para que a paginação funcionasse adequadamente.
    public function resultado()
    {
    $this->resultado = $this->conexao()->query(“select count(*) from ({$this->sql})”);
    $this->numeroResultados = $this->resultado->fetchColumn();
    return $this->numeroResultados;
    }

    public function sql()
    {
    $sql = str_replace(“SELECT”, “SELECT FIRST {$this->limite} SKIP {$this->offset()} “, “{$this->sql}”);
    return $sql;
    }

  5. Bom dia amigo, essa adaptação para firebird não esta funcionando, poderia explicar melhor?
    no mysql ta funcionando beleza, mas no firebird em resultado traz todos os registros. ja a barra de navegação ta funcionamento perfeito obrigado .

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *