Construyendo una tabla dinámica con PHP, MySQL, DataTables y Ajax

¿Cuántas veces te enfrentaste a la necesidad de mostrar información resumida en forma de tablas?

O, puesto de otro modo: ¿qué aplicación no requiere del uso de tablas?

Por supuesto que se puede usar HTML puro y quedará algo más o menos aceptable… pero con las herramientas (¡y los usuarios!) que tenemos hoy en día no podemos darnos el lujo de presentar una experiencia de usuario aceptable.

Debemos dar lo mejor que podamos.

Y lo mejor hoy en día implica interactividad.

Los usuarios quieren poder buscar, ordenar, paginar… prácticamente tener un Excel directo en su aplicación.

Ya te estarás imaginando el delirio de javascript que tendrías que ponerte a escribir para hacer todo esto desde cero, ¿no? De sólo pensarlo me dan ganas de retomar el curso de peluquería que dejé a la mitad 🙂

Afortunadamente no es necesario re-inventar la rueda.

Como podrás imaginarte, existen ya varios componentes que pueden adquirirse gratis (o a muy bajo costo) y que te ahorrarán muchísimas horas de trabajo y dolores de cabeza.

DataTables es un plugin de jQuery que resuelve muy bien esta necesidad, desafortunadamente la documentación es algo compleja de seguir…

Es por eso que me propuse escribir este artículo donde te presento un ejemplo completo de implementación de una tabla dinámica que utiliza DataTables combinado con un script php que actúa a modo de WebService REST para levantar los datos de una base.

Cómo se ve un DataTable

Empecemos por lo más importante: ¿sirve un DataTable para resolver tu necesidad?

Una imagen vale más que mil palabras, así que te muestro el ejemplo de una tabla en la que se visualiza el inventario de un comercio: una tabla en la que se verán los datos de cada uno de los productos (Id, Nombre, Precio):

No está mal, ¿no?

Repasemos lo que tenemos:

  • ¿Paginación? Lo tenemos!
  • ¿Búsqueda? Lo tenemos!
  • ¿Ordenamiento? Lo tenemos!

¿Qué más se le puede pedir a la vida? 🙂

Vamos ahora a ver qué hay detrás de la cortina.

El FrontEnd

El frontend consta de un archivo HTML que se ve así:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="//cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css">
    <title>DataTables example</title>
</head>
<body>
<h1>Behold... the power of DataTables!</h1>
<table id="theTable" class="display" style="width: 100%">
    <thead>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>price</th>
        </tr>
    </tfoot>
</table>
</body>
</html>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script>
<script type="application/javascript">
    $(document).ready( function () {
        $('#theTable').DataTable({
            ajax: '/get_data.php',
        });
    } );
</script>

Analicémoslo un poco:

<link rel="stylesheet" href="//cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css">

Esta parte incluye la hoja que aporta los estilos que necesita DataTables.

La parte principal es la tabla:

<table id="theTable" class="display" style="width: 100%">
    <thead>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>price</th>
        </tr>
    </tfoot>
</table>

Es importante que la tabla esté bien formada (Que tenga su sección thead, el tfoot es opcional).

No hace falta que le pongas un tbody, lo hace todo el plugin.

Luego tenemos el código JavaScript:

<script type="application/javascript">
    $(document).ready( function () {
        $('#theTable').DataTable({
            ajax: '/get_data.php'
        });
    } );
</script>

Es muy sencillito, se trata de invocar una función cuando el documento está cargado por completo.

Usando jQuery eso se logra con:

$(document).ready();

Y lo que ves dentro es el callback que se invocará cuando este evento ocurra.

$('#theTable')

Es la forma de seleccionar el objeto cuyo id es theTable.

En este caso se trata, obviamente, de la tabla que definimos en el HTML.

Y al invocar el método DataTable estamos transformando esa simple tabla en un objeto mucho más complejo.

Por último, este método recibe un parámetro: un objeto que contiene la configuración de la nueva tabla.

En nuestro caso se ve así:

{
   ajax: '/get_data.php'
}

Lo cual significa que le estamos pasando una configuración con una única propiedad: ajax y su valor (/get_data.php) es la URL de donde se obtendrán, mediante una llamada ajax, los valores con los que se rellenará la tabla.

El BackEnd

Ahora que viste cómo funciona el lado cliente, demos una recorrida por la parte del php:

<?php

try {
    $conn = new PDO('mysql:host=localhost;dbname=ecommerce','root','root');
} catch (PDOException $exception) {
    die($exception->getMessage());
}

$sql = "SELECT * FROM products";
$st = $conn
    ->query($sql);

if ($st) {
    $rs = $st->fetchAll(PDO::FETCH_FUNC, fn($id, $name, $price) => [$id, $name, $price] );

    echo json_encode([
        'data' => $rs,
    ]);
} else {
    var_dump($conn->errorInfo());
    die;
}

En este ejemplo estoy usando PDO aunque bien podría usar MySQLi ya que se trata de una base MySQL.

La primera parte:

try {
    $conn = new PDO('mysql:host=localhost;dbname=ecommerce','root','root');
} catch (PDOException $exception) {
    die($exception->getMessage());
}

Intenta realizar una conexión y, en caso de fallar emite un mensaje por pantalla para ayudar con el debugging.

Con este código:

$sql = "SELECT * FROM products";
$st = $conn
    ->query($sql);

Se intenta hacer la consulta de selección de los datos de los productos de la base.

Si la consulta fue exitosa buscamos el resultado para enviarlo al FrontEnd respondiendo a la llamada Ajax:

$rs = $st->fetchAll(PDO::FETCH_FUNC, fn($id, $name, $price) => [$id, $name, $price] );

echo json_encode([
    'data' => $rs,
]);

La primera línea se ve algo extraña, ¿no?

Paso a explicar 🙂

Un detalle que puede ahorrarte varios dolores de cabeza es comprender cómo DataTables espera recibir los resultados del webservice que le brinda los datos.

Se trata de un objeto json con este formato:

{
   data:[
     [ f1, f2, f3 ],
     [ f1, f2, f3 ],
     [ f1, f2, f3 ],
   ]
}

Donde f* corresponde a un campo del registro encontrado.

En este caso, para que todo salga bien, el php debe responder con algo como:

{
   data:[
     [ 1, 'Chair', 200.0 ],
     [ 2, 'Table', 500.0 ],
     [ 3, 'Shoes', 450.0 ],
   ]
}

Y hay que aclarar: DataTables es muy estricto con esto!

Es por eso que usé PDO::FETCH_FUNC (Bueno, por eso y porque soy un fanático de la programación funcional) para generar, en base a los registros obtenidos, el arreglo correspondiente.

Y luego es simple: con la función json_encode se genera el string que se requiere.

En conclusión

Espero que este pequeño ejemplo te haya ayudado a comprender lo que podés lograr con este plugin y un poco de php.

La próxima vez que tengas que mostrar resultados en forma de tabla probalo y comentá cómo te fué 🙂

Ah! Y si querés descargar el código completo podés hacerlo desde GitHub.

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a acceder mercados y clientes más sofisticados y exigentes

13 comentarios

  1. Una consulta y si en el footer quisiera vr la sumatoria de la columna de precio
    Como se haria?
    Gracias

  2. Hola! Gracias por el aporte.
    Cómo hago para que en la consulta SQL pueda agregar un WHERE de Fechas según lo seleccionado por el usuario?
    Es decir, en la inicialización del DataTable le puedo enviar al JSON ciertos parámetros para adecuar la consulta SQL?

    1. Hola Diego:

      ¿Probaste agregarle parámetros a la URL que usas para inicializar la tabla? Podrías intentar concatenar los valores de los campos fecha y del lado del PHP levantarlos usando $_GET.

      Intenta eso y si tienes problemas vuelve a consultar.

      Saludos,

  3. hola una pregunta quiero que al clickerar un boton una funcion jquery me canpture un atributo lo precesse y lo envie a la base de datos en la base o en el php se hace una validación si lo que trae post es ej 10 que me haga yn select y que luego me lo traiga en la respuesta ¿como puesdo hacer para que se almacene en el datatable apartir de alli? pensaba algo como en la respuesta se anexara a los columns de data table pero soy nuevo en la programación y no se como hacerlo porfa me puedes indicar

    1. Hola Gerardo:

      En principio no sería muy diferente. Sólo se requeriría cambiar la parte del backend para usar la API de mysqli. Por ejemplo, en lugar de:


      $conn = new PDO('mysql:host=localhost;dbname=ecommerce','root','root');

      Para armar la conexión se debería usar:


      $conn = mysqli_connect("localhost", "root", "root", "ecommerce");

      Y posteriormente usar mysqli_stmt_execute o similar.

      ¿Tuviste algún inconveniente realizándolo con mysqli?

  4. $rs = $st->fetchAll(PDO::FETCH_FUNC, fn($id, $name, $price) => [$id, $name, $price] );
    php indica que esta linea está erronea .-
    syntax error, unexpected ‘=>’ (T_DOUBLE_ARROW), expecting ‘,’ or ‘)’

    Podrias ayudarme?

      1. Hola:

        Esta sintaxis fn($id, $name, $price) => [$id, $name, $price] ) está disponible a partir de php 7.4, será que están usando una versión anterior?

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.