[Aporte] Paginación de Resultados SQL

Hola!

Yo sé que existe un tutorial para crear un sistema de paginación, pero este no es un tutorial, sino una clase PHP para paginar los resultados. La idea es que les sirva para reducir/acelerar el trabajo (para que no hagan el trabajo desde 0).

Les quiero compartir una clase de PHP que creé para paginar los resultados (no está completa, pero funciona como debe). Al final del tema podrán encontrar el enlace para descargar el archivo (es bastante largo, por eso no lo pegué en esta publicación). Por si acaso, si quieren leer el contenido de la clase, este está en inglés (me acostumbré a escribir el código y los comentarios en inglés :P).

La clase tiene posee lo siguiente:

  • Funciona (en teoría) con cualquier DBMS.
  • Permite añadir los enlaces Primero y último (para ir a la primer ya última página respectivamente).
  • Muestra los controles Anterior y Siguiente (y los deshabilita cuando corresponde).
  • El código HTML se genera 1 sola vez, pero se puede mostrar las veces que quieras. Esto permite mostrar el código antes y después de los resultados.

Me falta añadir:

  • Los controles para Saltar a la página X.
  • Controles que permiten cambiar los resultados por página.

Cómo Funciona

Supongo que lo mejor será un ejemplo:

paginacion.php (para ejemplificar, este archivo estará en la raíz del sitio web, al igual que la clase)
<!DOCTYPE html>
<html>
	<body>
	<?php
                // Primero deben incluir la clase
		require_once "DBKPagination.php";
		
                // $page es la página actual                
		$page = 1;
		
                // Comprueban que la variable existe y es un número
		if( isset( $_GET['page'] ) && is_numeric( $_GET['page'] ) )
			$page = (int)$_GET['page'];
		
                // $rpp son los Resultados por página
		$rpp = 10;
		
                // Lo mismo que antes: comprobar el contenido de la variable
		if( isset( $_GET['rpp'] ) && is_numeric( $_GET['rpp'] ) )
			$rpp = (int)$_GET['rpp'];
		
		// Se conectan a la base de datos
		$mysqli = mysqli_connect( 'localhost', 'usuario', 'contraseña', 'base de datos' );

                // Definen la consulta. Aquí no les puedo ayudar pues dependerá de la consulta que deban realizar después, aunque debería ser similar.
		$query = "SELECT COUNT(*) AS row_count FROM country";
		
		// Extraen el total de resultados que van a paginar (es obligación saber de antemano el total de resultados):
		$result_count = (int)mysqli_fetch_assoc( mysqli_query( $mysqli, $query ) )['row_count'];
		
		// El formato para la URL del los enlaces a paginar. Deben especificar la ruta
                // hacia el archivo que muestra los resultados.
                // Por defecto, el formato es /?page=%1$d&rpp=%2$d, lo que apunta a
                // la página principal en la raíz de su sitio web.
                // El %1$d, que será la página y %2$d que serán los resultados por página, son obligatorios, de
                // de lo contrario les arrojará un error.
		$url_format = '/paginacion.php?page=%1$d&rpp=%2$d';

                // Ahora se crea el objeto.
		$pagination = new DBKPagination( $result_count, $page, $rpp, $url_format );
		
                // Construyen la consulta y le agregan el límite (LIMIT N, X, donde N es el inicio y X el fin)
                // $pagination->getMySQLLimit() es específico de MySQL.
		$query = sprintf( "SELECT * FROM country %s", $pagination->getMySQLLimit() );

                // Ejecutan la consulta
		$results = mysqli_query( $mysqli, $query );

                // Muestran la paginación. Antes de utilizar esta función, asegúrense de 
                // haber asignado las opciones (las explico más abajo) que deseen.
		$pagination->printPages();
		
                // Iteramos sobre los resultados y los muestran
		if( $results ) {
			while( ( $row = mysqli_fetch_assoc( $results ) ) ) {
				echo "<div>$row[CountryName]</div>";
			}
		}
		else {
			echo "No Results!";
		}
		
                // Liberan los recursos
		mysqli_free_result( $results );
		mysqli_close( $mysqli );
		
                // Vuelven a mostrar los resultados (en caso de que el espacio que usan los resultados sea muy amplio - alto en realidad).
		$pagination->printPages();

		/**
		 * Otras Opciones
		 * 
		 * pageRange: cambia (setPageRange( $range )) o lee (getPageRange()) el valor del rango de páginas.
		 * Este rango asigna la cantidad de páginas hacia la derecha y la izquierda de la página actual. Si
		 * están en la página 10 y pageRange es 3 (por defecto), entonces se mostrarán las páginas desde
		 * 7 hasta 13. El rango va desde (página actual - pageRange) hasta (página actual + pageRange).
		 * Ejemplo: $pagination->setPageRange( 8 ); $pagination->getPageRange();
		 * 
		 * currentPage: cambia (setCurrentPage( $pagina )) o lee (getCurrentPage()) el valor de la página actual.
		 * Ejemplo: $pagination->setCurrentPage( 5 ); - Ir a la página 5.
		 * 
		 * resultsPerPage: cambia (setResultsPerPage( $rpp )) o lee (getResultsPerPage) la cantidad de resultados
		 * por página.
		 * Ejemplo: $pagination->setResultsPerPage( 5 ), hará que se muestren 5 resultados por página en lugar
		 * de los 10 por defecto. También se puede establecer al construir el objeto ($obj = new DBKPagination( ... )).
		 * 
		 * maxPages: lee (getMaxPages()) el total de páginas. Este valor es de solo lectura, vale decir, no
		 * se puede cambiar.
		 * 
		 * urlFormat: cambia (setUrlFormat( $formato )) o lee (getUrlFormat()) el formato de la URL que se usará
		 * en los enlaces.
		 * Ejemplo: $pagination->setUrlFormat( 'www.comocreartuweb.com/consultas/foro-general/%1$d/%2$d' );
		 */
	?>
	</body>
</html>

Bueno, lo que verán no será bonito porque no tiene ningún estilo, así que no se asusten xD.

El código generado por la clase sería algo así:

<!-- Como ejemplo, el total de resultados será 237, la página actual será la 10 y los resultados por página serán 10 -->
<div class="pagination">
	<a class="pag-link prev-link" href="/paginacion.php?page=9&amp;rpp=10" title="Ir a la página anterior (9)">Anterior</a>
	<a class="pag-link first-link" href="/paginacion.php?page=1&amp;rpp=10" title="Ir a la primera página">Primera</a>
	<a href="/paginacion.php?page=7&amp;rpp=10" class="pag-link" title="Ir a la página 7">7</a>
	<a href="/paginacion.php?page=8&amp;rpp=10" class="pag-link" title="Ir a la página 8">8</a>
	<a href="/paginacion.php?page=9&amp;rpp=10" class="pag-link" title="Ir a la página 9">9</a>
	<span class="pag-link current-page">10</span>
	<a href="/paginacion.php?page=11&amp;rpp=10" class="pag-link" title="Ir a la página 11">11</a>
	<a href="/paginacion.php?page=12&amp;rpp=10" class="pag-link" title="Ir a la página 12">12</a>
	<a href="/paginacion.php?page=13&amp;rpp=10" class="pag-link" title="Ir a la página 13">13</a>
	<a class="pag-link last-link" href="/paginacion.php?page=23&amp;rpp=10" title="Ir a la última página">Última</a>
	<a class="pag-link next-link" href="/paginacion.php?page=11&amp;rpp=10" title="Ir a la siguiente página (11)">Siguiente</a>
</div><!-- .pagination -->

Para darle estilo:

/* Div contenedor */
.pagination {}

/* Link para la página anterior y siguiente*/
.pagination .pag-prev-link,
.pagination .pag-next-link {}

/* Primera y última página */
.pagination .first-link,
.pagination .last-link {}

/* Para todos los enlaces entre el botón de primera y última página. Este es el estilo en común para todos */
.pagination .pag-link {}

/* Para la página actual - Típico efecto de deshabilitado */
.pagination .current-page {}

Creo que no me falta nada, así que les dejo el archivo:

Descarga desde Dropbox

Espero que les reduzca el trabajo. Demás está decir que si alguien no entiende algo o no pueden descargar el archivo, me debe avisar.

Saludos y suerte :)!
Se ve muy interesante tu clase intentaré incorporarla a mi script.
Saludos.