Comunidad de diseño web y desarrollo en internet

Paginación con PHP y MySQL

Un caso típico en el desarrollo web con PHP y MySQL es la funcionalidad de paginar resultados, si bien no es algo dificil muchos desperdician la potencialidad y malgastan los recursos de MySQL.

Para paginar resultados necesitamos saber 3 valores:

  1. Número de Página: este valor lo pide el usuario, asi que es fácil obtenerlo.
  2. Total de registros por página: normalmente lo define el programador con una constante
  3. Total de registros: necesitamos saber el total de registros para poder crear la cantidad de enlaces necesarios por página.

Donde se desperdicia el potencial y malgasta recurso de MySQL normalmente es en el 3 valor. Pues muchos ejecutan una consulta con LIMIT y otra consulta con un COUNT sin el LIMIT. Y es allí donde es el error, ya que MySQL ofrece las funciones: SQL_CALC_FOUND_ROWS y FOUND_ROWS.
  • SQL_CALC_FOUND_ROWS: calcula el número de resultados de una consulta sin LIMIT.
  • FOUND_ROWS: obtiene el resultado del último SQL_CALC_FOUND_ROWS ejecutados.

Aunque con estas funciones debemos igual ejecutar dos consultas, el calculo y tiempo de respuesta es mucho más rápido que haciéndolo con COUNT.

Ejemplo:

Código :

<?php

$link = @mysql_connect("localhost", "usuario", "password");
mysql_select_db("base_de_datos", $link);

// maximo por pagina
$limit = 5;

// pagina pedida
$pag = (int) $_GET["pag"];
if ($pag < 1)
{
   $pag = 1;
}
$offset = ($pag-1) * $limit;


$sql = "SELECT SQL_CALC_FOUND_ROWS id, nombre FROM tabla LIMIT $offset, $limit";
$sqlTotal = "SELECT FOUND_ROWS() as total";

$rs = mysql_query($sql);
$rsTotal = mysql_query($sqlTotal);

$rowTotal = mysql_fetch_assoc($rsTotal);
// Total de registros sin limit
$total = $rowTotal["total"];

?>

<table border="1" bordercolor="#000">
   <thead>
      <tr>
         <td>Id</td>
         <td>Nombre</td>
      </tr>
   </thead>
   <tbody>
      <?php
         while ($row = mysql_fetch_assoc($rs))
         {
            $id = $row["id"];
            $name = htmlentities($row["nombre"]);
         ?>
         <tr>
            <td><?php echo $id; ?></td>
            <td><?php echo $name; ?></td>
         </tr>
         <?php
         }
      ?>
   </tbody>
   <tfoot>
      <tr>
         <td colspan="2">
      <?php
         $totalPag = ceil($total/$limit);
         $links = array();
         for( $i=1; $i<=$totalPag ; $i++)
         {
            $links[] = "<a href=\"?pag=$i\">$i</a>"; 
         }
         echo implode(" - ", $links);
      ?>
         </td>
      </tr>
   </tfoot>
</table>


Advertencia:
  • En la configuración de PHP (php.ini) el valor mysql.trace_mode debe estar en Off. Si está en On por cada consulta que se haga a mysql se ejecuta un explain y esto hace sql_calc_found_rows inutil, por ende, found_rows siempre retornara 0. Este valor normalmente está en off, pero cabe la advertencia.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate