El editor de DataTables (V). Tablas con relaciones m-n (leer)

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

En el artículo anterior hemos visto como manejar datos de tablas con una relación 1 a n. Un miembro de personal podía residir en una ciudad, pero no en varias. Al mismo tiempo, una ciudad podía albergar a n miembros del personal. Lo mismo sucedía con los cargos.

Ahora la cosa se nos complica un poco. Vamos a ver que ocurre cuando tenemos tablas que se relacionan entre sí, en una relación de m-n. Cuando esto sucede, siempre hay una tabla intermedia, y la recuperación y gestión de datos es más laboriosa.

Si has seguido hasta aquí todos los artículos que he publicado de esta serie, te costará poco esfuerzo entender como hacemos funcionar este ejemplo. No obstante, dada su relativa complejidad si no tienes práctica, lo he dividido en dos artículos. En este primero no vamos, si quiera, a usar el editor. Sólo veremos los datos y manejaremos datatables como si sólo sirviera para eso. Será en el próximo donde veremos la versión completa, con editor y todo, de este ejemplo. ¿Te animas? Pues, hala. ¡Vamos allá!

EL ESCENARIO

Esta vez partimos de una base de datos del personal de una consultoría web, con tres tablas:

  • La tabla de desarrolladores, en la que se hacen constar su nombre, apellidos, fecha de ingreso en la compañia y salario bruto anual.
  • La tabla de especialidades.
  • La tabla intermedia, en la que se relacionan las especialidades con los desarrolladores que las practican.

Tenemos que tener en cuenta que cada desarrollador puede asociada una especialidad, o más de una, pero también se puede dar el caso de que tengamos desarrolladores que no tengan asociada ninguna especialidad (bien porque al darle de alta no sabemos sus especialidades, o porque estas aún no hayan sido creadas en la tabla). Además, se puede dar el caso de especialidades que no las practique ninguno de los desarrolladores que tenemos.

Por todo esto, deberemos programar nuestro objeto DataTables de tal modo que nos muestre la lista de desarrolladores, con todos sus datos, así como las especialidades que practican.

EL SCRIPT PRIMARIO

Lo primero que vamos a ver es el script primario. Este es donde menos tenemos que preocuparnos, ahora que aún no usamos el editor aunque, como verás, en el próximo artículo, que implementamos esta herramienta, la cosa cambia algo. Pero eso será entonces, y esto es ahora. El listado se llama articulo_editor_05_1.php y es el siguiente:

En las líneas de la 96 a la 101 hemos definido una columna (la primera, por lo que quedará a la izquierda), en la que no meteremos contenido, sino un icono para desplegar la lista de especialidades de cada desarrollador. Esto, en sí, no es nada nuevo Ya hemos conocido este recurso en un artículo anterior. Lo que sí es nuevo es que, cómo puedes ver, las columnas de datos no las hemos definido, cómo hacíamos antes, numerándolas, sino con el nombre del dato al que se refieren, tal cómo ves en las líneas de la 102 a la 105. Por esta razón, Cuando debemos desplegar la fila con la lista de especialidades, no debmos invocarla con un número de columna, cómo hacíamos en el artículo que te acabo de comentar, sino con el nombre del dato que se va a incluir en la fila complementaria desplegada. Lo ves en la línea 130. Al ver el script secundario, veremos de donde sale, en el JSON, el dato lista_especialidades. Por lo demás, todo lo que hay en el script primario lo conoces ya.

EL SCRIPT SECUNDARIO

Aquí la cosa se pone un poco más interesante. Cómo hemos comentado, tenemos dos tablas que se relacionan entre ellas, en una relación m-n, a través de una tabla intermedia. Esto da lugar a que, cuando hacemos una consulta de recuperación de datos en la tabla de desarrolladores, no podemos incluir la relación directemente en la consulta. Suponte que lo intentamos. La consulta podría ser algo similar a esto:

SELECT desarrolladores.*
FROM
desarrolladores,
especialidades,
relaciones_desarrolladores_especialidades
WHERE
relaciones_desarrolladores_especialidades.id_desarrollador = desarrolladores.id
AND especialidades.id = relaciones_desarrolladores_especialidades.id_especialidad
ORDER BY desarrollador.nombre LIMIT 1, 10;

Esto, que nos ha quedado tan cuco, no nos vale para nada, por lo siguiente: si un desarrollador tiene más de una especialidad, aparecerá más de una vez. Si no tiene asignada ninguna especialidad, no aparecerá. Lo del desarrollador que aparece más de una vez, ademas, nos da un problema adicional. Si cada desarrollador aparece cinco veces, por tener cinco especialidades, y hemos pedido diez registros a DataTables, al final sólo obtendremso datos de dos desarrolladores. A última hora, lo de los desarroladores que tienen más de una especialidad, se podría solucionar leyendo toda la lista de desarrolladores (suprimiendo la claúsula LIMIT), agrupándolos por desarrollador, cada uno con sus especialidades (esto ya lo haríamos procesando la matriz de datos en memoria recuperada de la consulta), y luego eliminando los que nos sobren (si tenemos 20 y queremos 10, debemos eliminar del dataset los que sobran). Proceso, todo él, laborioso, pero que puede llevarse a cabo y, desde luego, es fácil de programar. El problema es que no nos sirve para nada, porque no resuelve la cuestión de los desarrolladores que aún no tienen asignadas especialidades. Esos no nos los devuelve la consulta, por lo que nunca los podremos visualizar.

La solución pasa por una doble lectura. En primer lugar se hace una consulta para leer la lista de desarrolladores, de forma independiente, sin tener en cuenta las otras tablas. Esta lista de desarrolladores nos da un dataset previo. Después, leemos, para cada desarrollador, leemos sus especialidades, tanto si tiene más de una, cómo si no tiene ninguna.

Esto, evidentemente, da lugar a un proceso más lento, al tener que hacer más consultas a la base de datos, pero es la única solución.

Veamos el script secundario, cuyo listado es datos_externos_editor_05_1.php:

Observa, en las líneas de la 25 a la 31 que hemos definido, en principio, sólo columnas de la tabla de desarrolladores. Es en esta tabla donde vamos a hacer la recuperación de datos para el dataset previo. Como hemos comentado, aquí no vamos a tener en cuenta la tabla de especialidades, ni la tabla intermedia.

Cómo ves en la línea 76, dejamos como una cadena vacía la regla de relaciones. Como, en principio, sólo vamos a leer de una tabla, no hay nada que relacionar.

En las líneas 117 a 126 obtenemos el dataset previo con los datos de la tabla de desarrolladores exclusivamente.

En las líneas de la 130 a la 148 la cosa se pone más interesante. Recorremos, en un bucle, el dataset previo de desarrolladores y, a cada uno, le leemos las especialidades con las que está relacionado. Esta forma de hacer la consulta es lo que hace más lento el proceso general ya que, si tenemos diez desarrolladores, estamos haciendo diez lecturas a la base de datos. Si bien es cierto que un dataset puede contener, normalmente, un máximo de 20 o 30 registros (más no sería cómodo de manejar para el usuario), y con los servidores actuales, la demora es pequeña, existe y, con datasets más grandes, podría llegar a notarse un pequeño retraso. No obstante, es tan ridícula esta demora en la práctica, que resulta un pequeño precio que vale la pena pagar por la flexibilidad de obtener resultados.

Observa que, a partir de la matriz de especialidades obtenidas para cada desarrollador, le creamos dos nuevos datos a la matriz del dataset previo: uno con la matriz de los ids de las especialidades y otro dato con la matriz de sus nombres. Lo hacemos entre las líneas 142 y 147. Más adelante, cuando veas el final de este artículo, y el siguiente en el que emplearemos el editor, entenderás por qué lo hacemos de este modo.

Cuando creamos el dataset definitivo, fíjate, especialmente, en la línea 163. Le añadimos un campo con las especialidades listadas en una cadena. Es decir, la matriz con los nombres de las especialidades la convertimos en una cadena de texto. Esto se usará para las filas desplegables. Cada desarrollador tendrá, a la izquierda, su icono para desplegar una fila con la lista de especialidades, que será, precisamente, este dato. Observa que, si no tiene especialidades, le asignamos un texto de notificación. Esto es porque, si no, saldría la casilla vacía y al usuario podría parecerle un fallo de la aplicación.

Y por lo demás, ya lo tenemos todo. El código que necesitas (base de datos y scripts) los tienes en este enlace, para que te los descargues y puedas seguir el artículo. No dejes de leer los comentarios que he incluido en el código, que te ayudarán a entender todo el proceso. En el próximo artículo complementaremos este ejercicio con el editor, y aprenderemos varias cosas nuevas e interesantonas.

     

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *