> Manuales > Manual de CodeIgniter

Cómo realizar paginación de resultados en PHP y Ajax mediante el framework Codeigniter, para navegar sin recargar la página entera.

La paginación de resultados en informática es más vieja que el que os escribe este articulo. En el futuro a buen seguro se desarrollaran formas novedosas de paginar, aunque actualmente Codeigniter ofrece la librería ?pagination?. El único problema es que los enlaces que permiten navegar de una página a otra no son atractivos

Realmente las rutas de las distintas páginas de resultados son correctas, que tienen patrones de URL como controlador/1 , controlador/2 ? sin embargo hoy es deseable una mejor experiencia de usuario y con Ajax podemos mejorar este sistema considerablemente.

Con la ayuda de Ajax vamos a ocultar estos enlaces en la ruta de navegación y mostrar el contenido sin recargar la página entera. Quizás a priori pueda no parecer tan crucial la paginación mediante Ajax, pero hay casos en los que es realmente esencial. En el sitio de Youtube podrás encontrar una aplicación donde la paginación por Ajax hace la diferencia. Si estás viendo un video y haces clic en los links de paginación de los comentarios, el video no dejará de reproducirse, mientras visualiza los siguientes comentarios gracias a Ajax.

Nota: Para esta práctica asumimos que tenemos funcionando nuestro Codeigniter y hemos quitado el uso del index.php en nuestras rutas de navegación ( $config['index_page'] = ''; en el archivo config y modificado nuestro .htaccess ).
Esto se explica en el Manual de Codeigniter de DesarrolloWeb.com y también en la propia documentación del framework.

Creamos la tabla con los resultados a paginar

Vamos a crear una tabla llamada mensajes

CREATE TABLE IF NOT EXISTS `mensajes` (
`id` int(11) NOT NULL auto_increment,
`de` varchar(50) collate utf8_bin NOT NULL,
`mensaje` varchar(50) collate utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Además, vamos a crear un conjunto de mensajes ficticios:

INSERT INTO `mensajes` (`id`, `de`, `mensaje`) VALUES
(1, 'Mi jefe', 'Termina lo que tienes pendiente'),
(2, 'Mama', 'Hijo comunícate'),
(3, 'Profesor', 'Mañana es el examen'),
(4, 'Carlos', 'Págame'),
(5, 'Novia ', 'Ya no me atiendes como antes');
(6, 'Tio', 'Sobrino cuando vienes?'),
(7, 'Abuela', 'Querido nieto te he hecho un sueter'),
(8, 'Hermano', 'dónde tiraste mi tablet pc?');

Modelo para el paginador

Para este ejemplo usamos como nombre de pagina localhost. En tu caso solo debes de reemplazarlo por el nombre de tu página.

Una vez que hemos configurado nuestra conexión a la base de datos (en database.php). Podemos pasar a crear nuestro Modelo. Lo llamaremos modelo_paginador.php

<?php
class Modelo_paginador extends CI_Model {
   function __construct()
   {
      parent::__construct();
   }

   public function count_mensajes()
   {
      return $this->db->count_all_results('mensajes');
   }

   public function list_mensajes($limit, $offset)
   {
      $this->db->limit($limit, $offset);
      $query = $this->db->get('mensajes');
      return $query->result();
   }
}

Controlador

A continuación creamos nuestro controlador, asumiendo que usamos como nombre "Welcome".

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends CI_Controller {
   function __construct()
   {
      parent::__construct();
      $this->db = $this->load->database('default', TRUE);
      $this->load->library('pagination');
      $this->load->model('modelo_paginador', 'modelo');
      $this->load->helper(array('url'));
   }

   public function index($offset='')
   {
      $this->load->view('vista_mensajes'); // solo cargaremos la vista
   }

   public function lista($offset='')
   {
      $limit = 2;
      $total = $this->modelo->count_mensajes();
      $data['mensajes'] = $this->modelo->list_mensajes($limit, $offset);
      $config['base_url'] = base_url().'welcome/lista/';
      $config['total_rows'] = $total;
      $config['per_page'] = $limit;
      $config['uri_segment'] = '3';
      $this->pagination->initialize($config);
      $data['pag_links'] = $this->pagination->create_links();
      $data['title'] = 'Pagination';
      $this->load->view('lista_vista', $data);
   }
}
/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */

Vistas para el ejemplo de paginación

IMAGEN Vemos que en la función index cargamos una vista llamada 'vista_mensajes'. Por otra parte, en la función 'lista' tenemos la carga a la vista 'lista_vista'.

Para continuar vamos a crear estas vistas y también explicarlas un poco, ya que el asunto se sale de lo tratado en el manual de Codeigniter:

Comencemos con vista_mensajes.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
   <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
   <meta name="author" content="Heislersin" />
<script src="http://code.jquery.com/jquery-1.7.js"></script> <script type="text/javascript">
   $(document).ready(function(){
      $("#contenedor").load("/welcome/lista");
      $(document).on("click", "#pagination-digg li a", function(e){
          e.preventDefault();
         var href = $(this).attr("href");
         $("#contenedor").load(href);
      });
   });
</script>
<style type="text/css">
<!--
/* == Pagination === */
ul{border:0; margin:0; padding:0;}

#pagination-digg li{
   border:0; margin:0; padding:0;
IMAGEN    font-size:11px;
   list-style:none;
   margin-right:2px;
}
#pagination-digg a{
   border:solid 1px #c6baa4;
   margin-right:2px;
}
#pagination-digg .previous-off, #pagination-digg .next-off {
   border:solid 1px #c6baa4;
   color:#222222;
   display:block;
   float:left;
   font-weight:bold;
   margin-right:2px;
   padding:3px 4px;
}
#pagination-digg .next a, #pagination-digg .previous a {
   font-weight:bold;
}
#pagination-digg .active{
   background:#c6baa4;
   color:#FFFFFF;
   font-weight:bold;
   display:block;
   float:left;
   padding:4px 6px;
}
#pagination-digg a:link, #pagination-digg a:visited {
   color:#222222;
   display:block;
   float:left;
   padding:3px 6px;
   text-decoration:none;
}
#pagination-digg a:hover{
   border:solid 1px #222222
}
-->
</style>
</head>
<body>
<div id="contenedor">
</div>
</body>
</html>

La vista 'lista_vista.php' solo tendrá este contenido:

<ul class="nav" id="nav1">
<?php
foreach($mensajes as $p){
?>
<li><?=$p->de;?>: <?=$p->mensaje;?></li><?php
}
?>
</ul>
<ul id="pagination-digg">
<?=$pag_links;?>
</ul>

Este código fuente tiene algunos detalles que son importantes para que te funcione perfectamente en tu proyecto:

Para comenzar, la línea donde incluimos el script "http://code.jquery.com/jquery-1.7.js" deberá ser reemplazada por la ruta del archivo jQuery usado en tu proyecto, aunque si te viene bien usar el CDN de jQuery podrías dejar esa URL del script. Si lo quieres alojar en tu servidor, ten en cuenta de colocar el archivo en un directorio, por ejemplo "js", al cual le tienes que dar acceso en el archivo .htaccess.

Nota: Es importante señalar que este script Javascript basado en jQuery utiliza el método on(). Dicho método se utiliza para asignar eventos a elementos del documento HTML, o al propio documento como hacemos en el código, y está disponible solo a partir de la versión 1.7 de jQuery. Por ello, para que funcione, asegúrate que estás utilizando una versión de jQuery 1.7 o superior. En el ejemplo que teníamos antes en este mismo artículo utilizábamos el método live() para asignar los eventos, pero consume bastantes más recursos porque la llamada completa se hace al DOM. Algo que se ha arreglado con ON.

También hay una serie de detalles relacionados más bien con la programación en Javascript/jQuery que con el propio Codeigniter o PHP, ya que utilizamos ese lenguaje y el popular framework para realizar las conexiones con Ajax.

En concreto debemos prestar atención a la llamada al método load() de jQuery. Con la línea $("#contenedor").load("/welcome/lista"); estamos cargando el contenido de la paginación en un DIV llamado 'contenedor'.

Asimismo, podemos ver en las líneas siguientes el uso del método live(), que hace la magia de transformar el evento click, de un enlace normal de paginación, en un enlace Ajax:

$(document).on("click", "#pagination-digg li a", function(e){
   e.preventDefault();
   var href = $(this).attr("href");
   $("#contenedor").load(href); // esta línea carga el contenido
})

Nota: Insistimos que debes utilizar jQuery 1.7 o superior para que el método funcione. En caso contrario, puedes utilizar el método live() que sí funciona en versiones antiguas del framework. Para ello sustituye la línea que hace uso del método on() por esta línea de código:

$("#pagination-digg li a").live("click",function(e) {

Por último en nuestra carpeta application/config creamos un archivo llamado pagination.php, con el siguiente contenido:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// First Links
$config['first_link'] = 'First';
$config['first_tag_open'] = '<li>';
$config['first_tag_close'] = '</li>';

// Last Links
$config['last_link'] = 'Last';
$config['last_tag_open'] = '<li>';
$config['last_tag_close'] = '</li>';

// Next Link
$config['next_link'] = '»';
$config['next_tag_open'] = '<li>';
$config['next_tag_close'] = '</li>';

// Previous Link
$config['prev_link'] = '«';
$config['prev_tag_open'] = '<li>';
$config['prev_tag_close'] = '</li>';

// Current Link
$config['cur_tag_open'] = '<li class="active">';
$config['cur_tag_close'] = '</li>';

// Digit Link
$config['num_tag_open'] = '<li>';
$config['num_tag_close'] = '</li>';

/*
IMAGEN $config['full_tag_open'] = '<p>';
$config['full_tag_close'] = '</p>';

// First Links
$config['first_link'] = 'First';
$config['first_tag_open'] = '<div>';
$config['first_tag_close'] = '</div>';

IMAGEN // Last Links
$config['last_link'] = 'Last';
$config['last_tag_open'] = '<div>';
$config['last_tag_close'] = '</div>';

// Next Link
$config['next_link'] = '»';
$config['next_tag_open'] = '<div>';
$config['next_tag_close'] = '</div>';

// Previous Link
$config['prev_link'] = '«';
$config['prev_tag_open'] = '<div>';
$config['prev_tag_close'] = '</div>';

// Current Link
$config['cur_tag_open'] = '<b>';
$config['cur_tag_close'] = '</b>';

// Digit Link
$config['num_tag_open'] = '<div>';
$config['num_tag_close'] = '</div>';
*/

/* End of file pagination.php */
/* Location: ./system/application/config/pagination.php */

Este último es de valor estético para los enlaces de paginación

Al hacer clic en los enlaces el contenido se cargará esa página de resultados sin recargar completamente la pagina, con lo cual abramos logrado el objetivo de usar Ajax en nuestro sitio.

Eso es todo! Espero que cualquier persona pueda aprovechar estas notas para mejorar mediante Ajax la experiencia de usuario en los resultados que se muestran con paginación.

El link para descarga de los ejemplos se puede ver en: http://freakshare.com/files/1c6hruc7/pagination_codeigniter_ajax1.01.rar.html

Heisler Palma

Programador autodidacta, músico e investigador de la mente.

Manual