Codeigniter 3 paginacion

Paginación con Ajax y Codeigniter 3

Hugui Dugui

Una de la tareas más comunes en los sistemas de información es la paginación. Esto quiere decir ir mostrando una porción de los datos de una tabla con la finalidad de hacer más fácil la visualización de los registros.

Vamos a crear paso a paso lo necesario para generalizar esta tarea y hacer la paginación de cualquier tabla de manera sencilla.

Usaremos la biblioteca Pagination propia de Codeigniter, haremos los links de paginación con Bootstrap y cargaremos la tabla con jQuery y Ajax.

Para este tutorial  necesitaremos hacer la configuración básica de codeigniter 3 y también hacer llamadas ajax con codeigniter.


Comencemos por crear la DB con una tabla y los siguientes campos:
--
-- Table structure for table `usuarios`
--

CREATE TABLE `usuarios` (
  `id` int(11) NOT NULL,
  `nombre` varchar(40) NOT NULL,
  `apellido` varchar(40) NOT NULL,
  `correo` varchar(40) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `usuarios`
--

INSERT INTO `usuarios` (`id`, `nombre`, `apellido`, `correo`) VALUES
(1, 'Hugo', 'Martínez', 'ringhugos@gmail.com'),
(2, 'Gaby', 'Camacho', 'gaby@gmail.com'),
(3, 'Araceli', 'Morales', 'ara@hotmail.com'),
(4, 'Diana', 'Zapata', 'diana@yahoo.com'),
(5, 'Carlos', 'Camacho', 'carolos@hotmail.com'),
(6, 'Jose Luis', 'Sanchéz', 'jluis@gmail.com'),
(7, 'Marco', 'Dominguez', 'marco@yahoo.com.mx'),
(8, 'Israel', 'Mondragón', 'isramon@hotmail.com'),
(9, 'Federico', 'Buenavista', 'fede@gmail.com'),
(10, 'Marcela', 'Flores', 'mflores@gmail.com'),
(11, 'Eduardo', 'López', 'elopez@yahoo.com'),
(12, 'Noe', 'Garnica', 'ngarnica@hotmail.com'),
(13, 'Ricardo', 'Nava', 'richard@hotmail.com'),
(14, 'Gustavo', 'Gutiérrez', 'gusigusi@gmail.com'),
(15, 'Diana Paola', 'Garnica', 'asdf@gmail.D'),
(16, 'Diana Marcela', 'Marcos', 'adfxv@gmail.com');

--
-- Indexes for table `usuarios`
--
ALTER TABLE `usuarios`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for table `usuarios`
--
ALTER TABLE `usuarios`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=17;
COMMIT;

Ahora vamos haciendo un controlador llamado Inicio.php que por el momento no mostrará nada:

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

class Inicio extends CI_Controller {

    public function __construct()
    {
        parent::__construct();
    }

    public function index()
    {
        $datos['titulo'] = 'Paginación y búsqueda con Codeigniter y Ajax';
        $this->load->view('headfoot/header', $datos);
        $this->load->view('body/tabla');
        $this->load->view('headfoot/footer');
    }
}


Como lo hemos visto en tutorial de Maquetar index con vistas, separo la vista en header y footer que son las que se repiten en todas las secciones y dejo la vista de body/tabla donde maquetaremos, en este caso no se maquetará la tabla en sí, ya que se generará vía ajax, la vista contiene:

<section class="container">
  <div class="row">
    <div class="col-md-offset-3 col-md-6">
      <div id="table-data">
          <!-- Aquí la tabla obtenida de AJAX -->
      </div>

      <div id="links-paginacion">
         <!-- Aquí los links de paginación -->
      </div>

    </div>
  </div>
</section>

Para continuar vamos a hacer la configuración necesaria para usar la biblioteca Pagination, vamos a la carpeta config y agregamos un nuevo archivo llamado pagination.php que contiene el HTML de los links de la paginación con clases de bootstrap. Este archivo será cargado automáticamente cuando se llame al método initialize de pagination

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

$config["base_url"] = "#";
$config["use_page_numbers"] = TRUE;
$config["full_tag_open"] = '<ul class="pagination">';
$config["full_tag_close"] = '</ul>';
$config['first_tag_open'] = '<li class="page-item">';
$config['attributes'] = ['class' => 'page-link'];
$config['first_link'] = false;
$config['last_link'] = false;
$config['first_tag_open'] = '<li class="page-item">';
$config['first_tag_close'] = '</li>';
$config['prev_link'] = '&laquo';
$config['prev_tag_open'] = '<li class="page-item">';
$config['prev_tag_close'] = '</li>';
$config['next_link'] = '&raquo';
$config['next_tag_open'] = '<li class="page-item">';
$config['next_tag_close'] = '</li>';
$config['last_tag_open'] = '<li class="page-item">';
$config['last_tag_close'] = '</li>';
$config['cur_tag_open'] = '<li class="page-item active"><a href="#" class="page-link">';
$config['cur_tag_close'] = '<span class="sr-only">(current)</span></a></li>';
$config['num_tag_open'] = '<li class="page-item">';
$config['num_tag_close'] = '</li>';

La carga de datos será vía ajax y jQuery, para lo cual crearemos en assets/js/functions.js con lo siguiente:

$(document).ready(function() {

    // Cargar la tabla
    load_data_table(1, 'usuarios');

}); // document ready


Como vemos, al cargar el document ready se llama la función load_data_table la cual tiene la llamada ajax al controlador necesario que nos traerá los datos por página que hayamos configurado en el controlador. La función recibe:

  1. El número de página (entero)
  2. El nombre de la tabla (cadena)

Inicialmente se llamará con 1 en el primer parámetro que son los primeros datos de la paginación.

La función load_data_table contiene:

function load_data_table( page, table ) {
    
    var hostname = $("#hostname").val();

    $.ajax({
        url: hostname + "ajax_table/table/" + page + "/" + table,
        method:"GET",
        dataType:"json",
        success:function(resp) {
            //Carga la tabla en el id especificado
            $('#table-data').html( crearTabla(resp.data) );

            //Carga los links de pagination que vienen del backend
            $('#links-paginacion').html(resp.links_paginacion);
        }
    });
}


Vemos que en resp.data viene los datos de la paginación, la tabla la creamos con la función crearTabla() la cual tiene lo siguiente:

function crearTabla(datos) {

    var salida = "";
    salida = "<table class='table table-responsive'>" +
                    "<thead>" +
                        "<tr>" +
                          "<th scope='col'></th>" +
                          "<th scope='col'><span class='text-uppercase'>Nombre</span></th>" +
                          "<th scope='col'><span class='text-uppercase'>Apellido</span></th>" +
                          "<th scope='col'><span class='text-uppercase'>Correo</span></th>" +
                        "</tr>" +
                    "</thead>" +
                "<tbody>";


    $.each( datos, function( key, value ) {
        salida += "<tr id='row_" + value.id + "'>" + 
                    "<td>" + value.id + "</td>" + 
                    "<td>" + value.nombre + "</td>" + 
                    "<td>" + value.apellido + "</td>" +
                    "<td>" + value.correo + "</td>" +
                  "</tr>";
    });

    salida += '</table>';

    return salida;
} 


Ahora vamos a ver el controlador que hace la paginación,  es el controlador Ajax_table y el método table:

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

class Ajax_table extends CI_Controller {

	public function __construct()
	{
            parent::__construct();
	    $this->load->model("usuario_model");
	    $this->load->library("pagination");
	}

	public function table() 
	{
		if(!$this->input->is_ajax_request()){
			redirect('404');
		} else {
			$respuestas = array();
			
			//Obtener de la URL número de página, tabla a paginar
			//Estos vienen en la URL de la llamada ajax
			$page = $this->uri->segment(3);   //url/controller/method/(PAGE)/
			$table = $this->uri->segment(4);  //url/controller/method/page/(TABLE)

			$config = array();
			//Obtener el total de registros en la tabla
			$config["total_rows"] = $this->usuario_model->count_all('usuarios');
			//Mostrar 4 resultado por página
			$config["per_page"] = 4;
			$config["uri_segment"] = 3;
			$config["num_links"] = 1;
			$this->pagination->initialize($config);

			$pagina = $page; //url/controller/method/(PAGE)
			//Calcula el start del query
			$start = ($pagina - 1) * $config["per_page"];

			//getDataTable recibe (tabla, campos, where, columnaOrdenamiento, tipoOrden, start, end)
			$data = $this->usuario_model->getDataTable($table,
                                                                   array('id', 'nombre', 'apellido', 'correo'),
                                                                   array(),
                                                                   '',
                                                                   $order = 'ASC',
                                                                   $config["per_page"],
                                                                   $start);
			//Aquí van los datos de cada paginación
			$respuestas['data'] = $data;
			//create_links es un método propio de la librería que los crea
			$respuestas['links_paginacion'] = $this->pagination->create_links();
			
			header('Content-type: application/json; charset=utf-8');
			echo json_encode($respuestas);
			exit;
		}
	}
}


En este controlador usamos el modelo usuario_model, el cuál contiene 2 métodos, uno nos cuenta el total de registros de la tabla para hacer el cálculo y el otro es un método generalizado (que te puede ayudar en otros proyectos) para obtener los datos de una tabla:

<?php
class Usuario_model extends CI_Model{

  /**
   * Cuenta los registros activos/inactivos de una tabla
   * @param $tabla, nombre de la tabla
   * @return {int} Número de registros de la tabla
  */
  public function count_all( $tabla )
  {        
    return $this->db->count_all($tabla);
  }


  /**
   * Obtener datos de una tabla con condiciones (generaliza la obtención de datos)
   * @param {string} $tabla nombre de la tabla
   * @param {arry} $campos array de campos para el SELECT
   * @param {array} $where condiciones de WHERE en array clave=>valor
   * @param {string} $columnOrder nombre del campo para ordenar
   * @param {string} $order ASC | DESC
   * @param {int} $start inicio para el LIMIT de datos (se usa para la paginación)
   * @param {int} $end fin para el LIMIT de datos (se usa para la paginación)
   * @return {mix} success -> id de la insertada (int) | fail -> false 
  */
  public function getDataTable(
    $tabla, 
    $campos = array(), 
    $where = array(), 
    $columnOrder ='', 
    $order = 'ASC', 
    $end = 0, 
    $start = 0
  ) {
        
        if( count($campos) == 0 ) {
          $this->db->select("*");
        } else {
          $implode = implode(",", $campos);
          $this->db->select($implode);
        }

        $this->db->from($tabla);
        
        if( count($where) ) {
            $this->db->where($where);
        }

        if($end != 0){
            $this->db->limit($end , $start);
        }

        if ($columnOrder != '') {
          $this->db->order_by($columnOrder, $order);
        } 

        $query = $this->db->get();
        // Ver ultimo query:
        //echo $this->db->last_query(); exit; 
       
        return $query->result();  
    }
}


Ahora para finalizar, vamos a darle funcionalidad a los números de la paginación, eso lo haremos en el js con una función así, aprovecho este fragmento para poner todo el código js del ejemplo:

$(document).ready(function(){

    //Cargar la tabla
    load_data_table(1, 'usuarios', '');

    //Trae los siguiente datos al clik de la paginación
    $(document).on("click", ".pagination li a", function(event){
        event.preventDefault();
        var page = $(this).data("ci-pagination-page");
        load_data_table(page, 'usuarios', '');
    });

}); // document ready

function load_data_table( page, table ) {
    
    var hostname = $("#hostname").val();

    $.ajax({
        url: hostname + "ajax_table/table/" + page + "/" + table,
        method:"GET",
        dataType:"json",
        success:function(resp) {
            //Carga la tabla en el id especificado
            $('#table-data').html( crearTabla(resp.data) );

            //Carga los
            $('#links-paginacion').html(resp.links_paginacion);
        }
    });
}

function crearTabla(datos) {

    var salida = "";
    salida = "<table class='table table-responsive'>" +
                    "<thead>" +
                        "<tr>" +
                          "<th scope='col'></th>" +
                          "<th scope='col'><span class='text-uppercase'>Nombre</span></th>" +
                          "<th scope='col'><span class='text-uppercase'>Apellido</span></th>" +
                          "<th scope='col'><span class='text-uppercase'>Correo</span></th>" +
                        "</tr>" +
                    "</thead>" +
                "<tbody>";


    $.each( datos, function( key, value ) {
        salida += "<tr id='row_" + value.id + "'>" + 
                    "<td>" + value.id + "</td>" + 
                    "<td>" + value.nombre + "</td>" + 
                    "<td>" + value.apellido + "</td>" +
                    "<td>" + value.correo + "</td>" +
                  "</tr>";
    });

    salida += '</table>';

    return salida;
} 


Acá podemos ver en el gif el funcionamiento de la paginación con codeigniter 3 y ajax


No olvides que puedes descargar el zip de esta entrada con el proyecto completo listo para usar en tu localhost Paginación con Ajax y Codeigniter 3. Espero que me quieras compartir tus avances y/o dudas en el grupo de facebook del curso.

Si quieres puedes escribirme a ringhugos@gmail.com o al whatsapp para cualquier comentario o duda que tengas sobre este tutorial.