Hola!
Así que decidí que era tiempo de realizar otro post orientado a aquellos nobles trabajadores que se dedican al desarrollo web.
he notado que ha muchas personas se les dificulta hacer un paginador personalizado para los resultados de sus búsquedas en bases de datos, y realmente la cosa no es muy complicada, es solo de ir buscando “a tragos” en la base de datos.
Resulta que la definición del lenguaje MySQL 5.0 para la funcion SELECT, acepta la siguiente cadena:
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
Donde LIMIT es la funcion que delimita la cantidad de resultados que el query va a retornar. Esta expresión a su vez, acepta varias formas las cuales ejemplificare a continuacion:
- LIMIT 10 : Le dice al query que regrese únicamente los primeros 10 resultados row_count
- LIMIT 10,10 : Le dice al query que regrese los primeros 10 resultados a partir del resultado 10, osea, el primer numero es offset y el segundo row_count
Bien con este conocimiento básico sobre el “comando” limit en nuestros querys SELECT, podríamos idear una forma facil de paginar nuestros resultados usando parámetros en la dirección url.
Vamos a suponer que tenemos una tabla cliente definida de la siguiente forma:
id | nombre | direccion | telefono |
---|---|---|---|
1 | Juan | Ciudad | 123456 |
2 | Pedro | Ciudad2 | 123456 |
…
Y vamos a suponer ademas que esta tabla tiene unos 300 registros de clientes. Entonces nuestro requerimiento es paginar de 50 en 50 nuestra tabla y presentarla en un formato amigable al usuario.
Manos al código!!
<html>
<head>
<title>Un simple paginador</title>
</head>
<body>
<?php
//primero obtenemos el parametro que nos dice en que pagina estamos
$page = 1; //inicializamos la variable $page a 1 por default
if(array_key_exists('pg', $_GET)){
$page = $_GET['pg']; //si el valor pg existe en nuestra url, significa que estamos en una pagina en especifico.
}
//ahora que tenemos en que pagina estamos obtengamos los resultados:
// a) el numero de registros en la tabla
$con=mysqli_connect("localhost","ricardogeek","passw0rd","mi_db");
$conteo = mysqli_query($con,"SELECT COUNT(*) as conteo FROM clientes");
while($row = mysqli_fetch_array($result))
{
$conteo = $row['conteo'];
}
//ahora dividimos el conteo por el numero de registros que queremos por pagina.
$max_num_paginas = intval($conteo/50); //en esto caso 50
// ahora obtenemos el segmento paginado que corresponde a esta pagina
$segmento = mysqli_query($con,"SELECT * FROM clientes LIMIT ".(($page-1)*50).", 50 ");
//ya tenemos el segmento, ahora le damos output.
echo '<table>';
while($row = mysqli_fetch_array($result))
{
echo '<tr>
<td>'.$row['id'].'</td>
<td>'.$row['nombre'].'</td>
<td>'.$row['direccion'].'</td>
<td>'.$row['telefono'].'</td>
</tr>';
}
echo '</table><br/><br/>';
//ahora viene la parte importante, que es el paginado
//recordemos que $max_num_paginas fue previamente calculado.
for($i=0; $i<$max_num_paginas;$i++){
echo '<a href="MiScript.php?pg='.($i+1).'">'.($i+1).'</a> | ';
}
?>
</body>
</html>
ahora bien algunas explicaciones con estilo FAQ:
- Que significa la variable $max_num_paginas? Es el numero de paginas que tendra nuestro paginador. se calcula obteniendo el total de registros y se divide dentro de la cantidad de registros por pagina. En este ejemplo esa cantidad es 50.
- Por que en la variable segmento se le resta 1 a la variable $page? para calcular el offset, el multiplicador tiene que ser siempre 0-based. es decir, si $page = 1, el ofset debe ser 0 para obtener un LIMIT 0, 50 (los primeros 50 registros despues del registro 0) y si $page = 2, obtener un LIMIT 50,50 (los primeros 50 registros despues del registro 50), y asi sucesivamente.
- Por que a los links del paginador se le suma 1 a la variable $i? para mantenerlo humanamente entendible (los simples mortales cuentan a partir de 1). y para respetar nuestra regla el paginador anteriormente descrita.
Espero que lo encuentren fácil de hacer :), si alguien lo pide en los comentarios, pongo un .zip con un ejemplo completo.
Saludos!
EDIT: A peticion de Isabel, aqui esta la descarga de un ejemplo de paginador completo:
hola, muy interesante tu explicación, podrías poner un archivo con un ejemplo por favor?
Gracias
Claro que si :3 en seguida!
Hola, muy bien, falto una cosa a la primero consulta ponerle el limit por que para aquellos que cambié la primera consulta una búsqueda o algo. Por que ahora como lo tienes siempre tendría el numero de registros total.
conteo = mysqli_query($con,”SELECT COUNT(*) as conteo FROM clientes”);
LIMIT “.(($page-1)*50)
Un Saludo,
Esa que mencionas es precisamente para eso, para obtener el numero total de registros, y luego dividirlo dentro del total de registros por pagina que deseamos. Mas abajo hay otro query que ya regresa los datos paginados acorde a esto. Como ves el query dice “COUNT(*) as conteo” lo cual regresa un valor entero y no una tupla, este valor entero luego se divide dentro del numero de resultados por pagina y el resultado de esta division nos da el total de paginas (los links al pie de la tabla).
Saludos.-
Que pasa si tenemos 9 registros y los paginamos con el codigo tal como esta.
Suponiendo que vamos a mostrar registros de 4 en 4
$max_num_paginas = intval($conteo/4);
9/4 = 2 usando la funcion intval, mostrara 2 paginas solamente siendo que deberia mostrar 3 pues son 9 registros.
Yo lo que hice fue hacer uso de un if y ahora si pagine correctamente 9 resultados, donde $num es el total de registros seleccionados.
Gracias Ksn!
Aguda observacion! si no te importa incluire la correccion en el ejemplo.
Gracias!
Hola.. oie y si mi estructura es DAO???
tengo mi clase para conectar y ejecutar consultas,
y mi DAO desde el cual creo, modifico, busco y borro registros.
Te amo! No he encontrado sitio donde esté mejor explicado
Pa una pregunta.
El archi
Pa una pregunta el archivo myscript.php cual es???
El archivo myscript.php, es un archivo de ejemplo nada mas, se refiere a la pagina en donde escribiste todo este código.
Gracias por facilitarlonoslo
Muchaaas Graciass, pensé que no servia pero ya entendi bien como es y sirve perfectamente.
Para entender mejor hagalon 1° en el servidor de base de datos para saber q es lo que se hace
Esa explicacion es muy simple y rudimentaria , porque en realidad pagina datos estaticos sin mas , en una aplicacion real se plantean los problemas de que hacer si se busca por filtros , e ir paginando estos resultados ….. ese es el verdadero problema de las paginaciones , sin mencionar , la ordenacion etc….
Sep, la explicación es básica, pero quien entendió el concepto, bien entendido, podrá aplicar filtros al query, incluso paginar con ajax (solo cambiaría el output), si estas usando un framework es cuestion de agregar las restricciones a tu modelo y es aun mas fácil de lo que aquí planteo. Si publicara algo mas complejo estaría truncando tu habilidad de abstraer un problema complejo a partir de un concepto “simple y rudimentario” y finalmente te convertirías en un pésimo programador.
Muy fácil muchas gracias, pero en vez de poner:
$max_num_paginas = intval($conteo/50); //en esto caso 50
puse$max_num_paginas = ceil($conteo/50); //en esto caso 50
Hola a todos hice algunos ambios y trate de simplificarlo y tome encuenta los comentarios aqui mi resultado:
$get = mysql_query("SELECT * FROM catalogs");
$count= mysql_num_rows($get);
$page = 1;
$limit = 10;
if(array_key_exists('pg', $_GET)) {
$page = $_GET['pg'];
}
if($count/$limit>intval($count/$limit)){
$max_num_paginas = intval($count/$limit)+1;
}
else {
$max_num_paginas = intval($count/$limit);
}
$catalogs = mysql_query("SELECT * FROM catalogs ORDER BY list ASC LIMIT ".(($page-1)*$limit).", $limit");
while($catalog= mysql_fetch_array($catalogs)) { .... OUTPUT
todo funciona bien pero el resultado es terrible, me aparecen un in numero de links
se puede tener una variable que se llame $resultados y en ella guardar el numero de resultados que se quiera por pagina.
mysqli_query($con,”SELECT * FROM clientes LIMIT “.(($page-1)*$resultados).”, $resultados “);
Es mejor usar la función CEIL para el máximo de páginas. Luego para mostrar, sólo hay que usar for($i=0; $i<$max_num_paginas;$i++) y todo va genial. GRACIAS!
Me sale este error:
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, null given in /home/u553659903/public_html/paginador.php on line 16
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, null given in /home/u553659903/public_html/paginador.php on line 28
Me ayudo mucho el ejemplo. de verdad gracias… solo un aporte: Para obtener el numero de paginas correcto, demos quitar el INT() y que la linea quede asi: $max_num_paginas = $conteo/5; Ya que la division de los numeros no tiene porque ser obligatoriamente un Entero sin decimales. de esta forma obtendras la ultima pagina con el resto de registros que te queden.
Gracias por el ejemplo!
Tienes algo para paginar comentarios y respuestas? gracias
Bueno vamos a intentarlo!
el articulo es muy bueno, no obstante dos cosas:
Al usar intval()para redondear el numero de paginas, esto redondea a la baja lo cual hace que se pierda la ultima pagina, seria mas conveniente utilizar ceil() que redonda a la alza.
Y usando mysqli_num_rows() puedes obtener el numero total de elementos de la consulta, de esta forma te evitas el bucle para contarlos.