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 respostas em “Classe de Paginação com PDO”
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!
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…
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
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;
}
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 .
Hum. Precisaria ver isso. Mil desculpas!