Paginado web dinámico y http_build_query

Tutorial sobre como crear páginados para el contenido de nuestra web mediante el uso de enlaces, consultas y php.

consultas sql php y html sql select Programacion web

En este tutorial aprenderás a realizar un paginado web sencillo pero eficiente. Una implementación sencilla que te simplificará la vida a la hora de realizar tus aplicaciones web.

¿ Qué es el paginado de contenidos ?

Desde que las páginas de contenido dinámico existen también lo hace el paginado de sus contenidos. 

Un buen paginado de contenidos permitirá al usuario navegar por páginas dinámicas visualizando la mínima cantidad posible de datos, saber en qué posición se encuentra en todo momento respecto al resto de datos, además de hacerse una idea global de la cantidad de información que puede llegar a visualizar.

Las partes de un paginado web

El paginado de contenidos se fundamenta en un flujo de datos entre la base de datos (mediante consultas) y la interacción del usuario. Este flujo de información se conforma de varias partes:

  1. Un número determinado de registros a mostrar.
  2. El total de registros disponibles en la base de datos.
  3. Los enlaces HTML que llevan a las distintas paginas posibles.
  4. Una consulta a la base de datos que variará según la página a visualizar.

Cómo crear un paginado web paso a paso

El orden de las partes que te he comentado justo arriba es el que normalmente se sigue de forma organizada para crear un paginado de contenidos. Pero para aprender a realizar el paginado voy a explicártelo en un orden distinto que te será más fácil de entender:

1. Mostrar el contenido sin paginar

Aunque sea redundante, empecemos por el principio. Lo primero que hacemos cuando queremos crear una página dinámica es cargar la información de nuestra base de datos en nuestro código php, por ejemplo para las noticias de la web:

<?php
$query = "SELECT *
          FROM noticia";
$_DB = new PDOAdmin(); 
$noticias = $_DB->execute($query, 1);
?>

En este script he cargado todas las noticias de la web con mi Clase de conexión a base de datos simplificada. En este punto, podría mostrar el contenido de las noticias con un simple bucle foreach:

<h2>Noticias de la web</h2>
<?php
foreach ( $noticias as $noticia ) {
    echo '<h3>' . $noticia['titulo'] . '</h3>';
}
?>

2. El límite de registros a mostrar

Tras mostrar todas las noticias de nuestra web, vamos a pasar a determinar la primera parte del paginado: El número máximo de registros por página. El número de registros a mostrar (en el ejemplo noticias) es subjetivo, dependerá de nuestra estrategia a la hora de componer las páginas y lo que ocupe cada elemento mostrado.

Sigamos con el ejemplo propuesto. Como el número de noticias es elevado, más de cien, he decidido mostrar tan solo quince noticias de cada vez. Así que voy a modificar mi consulta para que tan solo traiga quince noticias:

<?php
$query = "SELECT *
          FROM noticia
          LIMIT 15";
$_DB = new PDOAdmin(); 
$noticias = $_DB->execute($query, 1);
?>

Con la instrucción SQL LIMIT limito el número de resultados que me devolverá la consulta, ahora ya he indicado cual es el número de registros que voy a mostrar por página, en el próximo punto abordaremos como saber las páginas disponibles.

Como último dato te comento un dato a tener en cuenta y es que Google tiene una opinión respecto al paginado de contenido, y es que se debe priorizar la visualización de la web en la parte superior de esta, es decir, que un usuario nada más abrir una página web visualice la mayor parte de la página por el navegador sin hacer scroll.

El número de registros a mostrar (en el ejemplo noticias) es subjetivo, dependerá de nuestra estrategia a la hora de componer las páginas y lo que ocupe cada elemento mostrado.

3. El total de registros y el número de páginas

Para poder saber cuánto contenido hemos dejado sin mostrar o, lo que es lo mismo, cuantas páginas tenemos disponibles debemos conocer cuál es el total de registros del contenido que se mostrará en la página. En el ejemplo, vamos a ver cuántas noticias tengo en total mediante una consulta:

<?php
$query2 = "SELECT COUNT(*) as n_noticias
           FROM noticia";
$_DB = new PDOAdmin(); 
$resultado = $_DB->execute($query, 2);
$total_noticias  = $resultado['n_noticias'];

Como ves he obtenido el total de noticias mediante la función COUNT(*). Ahora que tengo el total voy a calcular el número de páginas totales mediante la siguiente operación:

$paginas = ceil( $total_noticias/15 );
?>

La operación es tan simple como dividir el total de registros ($total_noticias) entre el número de registros por página. He redondeado hacía arriba con la función php ceil() para no obtener un número decimal como podría ser 7.4 páginas.

Ahora ya podemos mostrar en nuestra web los enlaces a las páginas disponibles con HTML y CSS, un ejemplo sencillo:

<?php
for( $i = 0; $i < $paginas; $i++ ){
    $pagina_texto = $i + 1;
    echo '<a href="?pag=' . $i .  '">' . $pagina_texto . '</a>';
}
?>

Observa que he añadido a la url actual la información de la página adecuada para cada botón mediante $_GET. La página tendrá el valor de la página que visualiza el usuario menos uno, ya que las páginas empezarán en cero.

4. Mostrar el contenido de la página seleccionada

Ahora que los usuarios pueden seleccionar una página de las entre las disponibles tan solo nos queda utilizar la información que los enlaces insertan en la url ( $_GET ). 

<?php
$pagina = isset($_GET['pag']) ? $_GET['pag'] : 0;

Si el usuario ha pinchado en el enlace de una página, utilizaré ese dato, en caso contrario estaré en el inicio del contenido y por lo tanto deberé utilizar el valor cero (el primer elemento de primera página de contenido).

$offset = $pagina * 15;

Ahora nos falta saber en qué registro exacto, de los que traerá la consulta, debemos indicar que empiece a contar. Este concepto se define así: El primer registro, es decir, la primera noticia, tendrá el offset cero, el registro dieciséis ( que será la el primer registro de la segunda página de contenido) tendrá el offset catorce. En la siguiente lista te muestro los offset de las páginas para mi consulta de quince registros:

  1. Del registro 0 al 14
  2. Del registro 15 al 29
  3. Del registro 30 al 44
  4. Del registro 45 al 59
  5. Del registro 60 al 74
  6. Registro 75 al 89
  7. ....

Si mi límite de registros fuera por ejemplo 10 entonces quedaría así:

  1. Del registro 0 al 9
  2. Del registro 10 al 19
  3. Del registro 20 al 29
  4. Del registro 30 al 39
  5. Del registro 40 al 49
  6. ....

Ahora vamos a modificar la consulta de las noticias para que los quince registros que obtiene sean exactamente de la página solicitada. Para ello utilizamos la sentencia especial OFFSET de SQL:

$query = "SELECT *
          FROM noticia
          OFFSET $pagina LIMIT 15";

Con esta pequeña modificación le indicamos a nuestro sistema de gestión de base de datos (MySQL por ejemplo) que debe devolvernos los registros empezando en el offset y contando el número de registros del LIMIT.

5. Mostrar al usuario la página en la que se encuentra

¿Qué nos falta? Pues indicar en los enlaces de las páginas cuál de ellas es la activa, esto es tan sencillo como mirar la variable de la página $pagina e indicar en HTML una clase CSS, por ejemplo active.

<?php
for( $i = 0; $i < $paginas; $i++ ){
    $pagina_texto = $i + 1;
    $clase = '';
    if( $pagina == $i )
       $clase = 'active';
    echo '<a href="?pag=' . $i .  '" class="'$clase'" >' . $pagina_texto . '</a>';
}
?>

Final: Código de Paginado de contenidos

Pues ya hemos terminado, para finalizar voy a dejarte el código final al completo:

<?php
$_DB = new PDOAdmin(); 
$pagina = isset($_GET['pag']) ? $_GET['pag'] : 0;
$offset = $pagina * 15;
//las 15 noticias de la página
 
$query = "SELECT *
         FROM noticia
         OFFSET $pagina LIMIT 15";
$noticias = $_DB->execute($query, 1);
//total de páginas
$query2 = "SELECT COUNT(*) as n_noticias
           FROM noticia";
$resultado = $_DB->execute($query2, 2);
$total_noticias  = $resultado['n_noticias'];
$paginas = ceil( $total_noticias/15 );
 
//VISTA **********************
foreach ( $noticias as $noticia ) {
   echo '<h3>' . $noticia['titulo'] . '</h3>';
}
//ENLACES HTML DE LA PAGINA
for( $i = 0; $i < $paginas; $i++ ){
    $pagina_texto = $i + 1;
    $clase = '';
    if( $pagina == $i )
       $clase = 'active';
    echo '<a href="?pag=' . $i .  '" class="'$clase'" >' . $pagina_texto . '</a>';
}
?>

A pesar de que todo el código lo he programado en línea y en un solo fichero piensa que normalmente las consultas y el código que realiza los cálculos irían en un fichero de MODELO y los enlaces en la VISTA de una web desarrollada en MVC (modelo vista controlador).

Extra: Añadir paginado a formulario GET

En este tutorial he tratado de explicar una forma sencilla de añadir paginado a una página de contenido dinámico simple como noticias, post o productos. Pero si lo que pretendes es añadir paginado a un formulario de tipo GET te encontrarás con el problema de mantener la información del formulario mientras añades la página.

Utilizando la función http_build_query() de PHP 5 y 7 podemos manipular la query de la url (la información GET). En el siguiente ejemplo voy manipular la página de un enlace sin preocuparme por la información que pueda haber en la query GET de la url:

<?php
$query = $_GET;
for( $i = 0; $i < $paginas; $i++ ){
    $pagina_texto = $i + 1;
    $clase = '';
    if( $pagina == $i )
       $clase = 'active';
    //variable que contiene la página
    $query['pag'] = $i;
    //obtengo el texto que irá después de la url 
    $url_query = http_build_query($query);
    //indico en el enlace la nueva query de la página adecuada
    echo '<a href="?' . $url_query . '" class="'$clase'" >' . $pagina_texto . '</a>';
}
?>

Descarga de ficheros

Te dejo aquí los ficheros para probar tranquilamente con tu páginado de contenidos y desarrollar a partir de ahí:

Sobre el autor

Javier Gómez Redactor en Srcodigofuente.es

Javier Gómez

Ingeniero técnico en informática de gestión. Desarrollador web freelance y profesor de desarrollo web a partes iguales. Testarudo autodidacta, creativo, perfeccionista y alma libre.

Cargando comentarios

Utilizamos "cookies" para información estadística. Si continúas navegando aceptas su uso.