Tablas en Drupal: Haciendo una tabla perfecta


Sobre el artículo

Este artículo, basado en el original "Tables in Drupal: Making a perfect table", escrito por Kevin Bowler, ha sido traducido por Miguel Ángel García al español.

El copyright pertenece a Kevin Bowler, por lo que deberán dirigirse a éste para los agradecimientos y cualquier comentario sobre el código.

Por favor, use el foro en castellano únicamente para comentarios sobre la traducción.

¿Alguna vez has...?

¿Alguna vez ha querido hacer una tabla en Drupal usando theme_table? Bien, ¿qué tal si le añadimos unos links extra, por ejemplo para opciones (Edit/Delete etc)? ¿Y si la ordenamos? ¿Algo de paginación? Bien, este tutorial le mostrará cómo hacer todo esto. ¡Después de esto será el máster de las Tablas en Drupal!

Paso 1: Difinir las cabeceras

¿Cuáles son los nombres de las columnas?

Suena estúpido, pero será útil más adelante durante el proceso.

Puede encontrarlos buscando la tabla correspondiente en su base de datos.

Debería terminar con un array de cabeceras como éste:

$headers = array("data" => t([field_name]));

Claro que es necesario sustituir el texto entre corchetes con el nombre del campo de la base de datos.

Paso 2: Define los extras

Los extras son las acciones que se quieren realizar sobre los datos, como editar o borrar el dato.

La manera más limpia y clara de hacer esto es crear una función de ayuda separada a la que se pueda llamar mientras se construye la tabla principal.

/**
* Función de utilidad para construir enlaces para la tabla
*/
function _generate_options ( $id )
{
  $links = l(t('Edit'), "admin/settings/data/edit/$id") ."  " . l(t('Remove'), "admon/settings/data/remove/$id");
  return $links;
}

Realmente no es demasiado código, y se observa que puede ser muy manejable. Simplemente construya un enlace (utilizando la función l() ) con acciones basadas en las elecciones de la cabecera, y añada el id de la columna en el enlace, con el fin de asegurar que se actúa sobre el elemento correcto.

Uso el subrayado al principio del nombre de la función para marcar que es una función 'privada'; sólo se va a utilizar de forma interna en este módulo.

Esta función se llamará en el paso 4, durante el proceso de los datos para construir la tabla actual.

Paso 3: Ejecuta la consulta

Ahora tenemos que extablecer la consulta para obtener todos los datos de nuestra deseada tabla.

$sql = "SELECT [fields] FROM {table}";

Como puede observarse, no es una query demasiado compleja. Puede pensarse que es ineficiente, y así es.

Dejaremos que Drupal se ocupe de esto más adelante (paso 6).

Paso 4: Procesado de datos

Es en este paso cuando transforman los datos de base de datos en un array, preparado para ser introducido con un tema en una tabla.

// ejecutar la query
$result = db_query ( $sql );
if ( $result )
{
  // Establecer el array de datos
  $data = '';
  $i = 1;
  // Bucle básico para obtener los datos
  while ( $tmp = db_fetch_array ( $result ) )
  {
    $data[$i] = $tmp;
  }
}

Puede ser tan simple o tan complejo como se desee. Aquí sólo se cubrirá un ejemplo de personalización.

Eliminando el ID

A veces no se desea mostrar al usuario el ID de un elemento, pero se necesita para generar la URL o los extras.

De esta manera, después de usarlo en el código anterior se puede 'desestablecer'.

Simplemente inserte la línea siguiente al final del bucle while ( ¡¡¡ pero dentro de él !!! ):

unset ( $data[$i]['id'] );

Ahora el ID no requiere una cabecera, por lo que no es necesario seleccionar el ID en la query y no tiene que mostrarse al usuario cómo se ordenan los datos.

Paso 5: Establecer un tema para la salida

De esta forma, ahora vamos a establecer un tema para la salida, y obtendremos una tabla básica:

theme ( 'table', $headers, $data );

Lo que se está haciendo es llamar a la función theme, y pasarle el tipo del elemento a renderizar, en nuestro caso una tabla.

Esto llama a la función interna para el tema de la tabla, llamada theme_table(), y se le pasan los dos parámetros; el array de cabeceras, y el array de datos (ambos definidos antes en el código).

Si lo único que busca es una tabla simple, puede dejarlo aquí.

De todas maneras, es muy fácil añadirle algunas características interesantes a la tabla, de forma que impresione a la gente con su asistente de tablas Drupal, ¡por lo que siga leyendo!

Paso 6: El paginador

Ok, esta tabla está bien, pero ¿qué ocurre si tiene 1.000 registros? ¡Eso hace una página muuuuuuuuuy larga, y una consulta masivamente ineficiente! ¡Pobre servidor de bases de datos!

Así, se le puede pedir a Drupal que añada un paginador a nuestra consulta, y sólo devuelva cada vez un número de filas predefinido:

$limit = 10;
// generar una consulta paginada
$result = pager_query ( $sql, $limit );

¿Parece simple? Bien. Lo es. Lo único que estamos haciendo es reemplazar la llamada a db_query con una llamada a pager_query, y pasándola un límite, o el número de filas a devolver por página.

Si quería ser realmente listo, este valor se podría establecer en una página de administracción, y añadida aquí usando variable_get (Le dejaré éste a usted, ¡no me gustaría fastidiarle toda la diversión!).

Ésta es una de las cosas a hacer antes de que nuestro paginador funcione. Hay que establecer el tema de la salida como una tabla paginada.

No se preocupe, no es difícil, y no requiere cambiar mucho código.

Todo lo que haremos es reemplazar la llamada actual a theme por:

$output = theme (
  'table',
  $headers,
  $data
);
$output .= theme ( 'pager', NULL, $limit, 0 );
print theme ( 'page', $output );

¿Qué es lo que estamos haciendo aquí?

  1. Llamar a theme para establecer el tema de nuestra tabla original, y almacenando el resultado en una variable.
  2. Añadir el paginador a esa variable llamando a theme_pager, pero esta vez usando 'pager' como tipo, para así llamar a la función con subrayado theme_pager, y concatenarlo con nuestra variable.
  3. Finalmente, establecemos el tema a la salida como una página a renderizar lista para mostrar.

Simple, ¿no?

Paso 7: Ordenación

El paso final en la ruta de la Tabla Zen es la ordenación de la tabla. ¿No estaría bien poder ordenar por un campo específico distinto del ID, o simplemente cambiar el orden de la tabla, al vuelo?

Bien, con unos pocos cambios en nuestro código, ¡podemos!

¿Recuerda el array de cabeceras que creamos anteriormente? Bien, ahora nos va a venir de perlas.

Para que la ordenación de la tabla funcione, tenemos que indicarle cómo ordenar los datos. Se hace con el array de cabeceras. Simplemente se le da a cada cabecera (que es el nombre del campo en la base de datos) el orden por el que ordenar los datos.

En el siguiente ejemplo, usaremos el campo 'Name'.

Así, nuestro array de cabeceras queda de la forma:

$headers = array (
  array ( 'data' => t('name'), 'field' => 'name', 'sort' => 'desc' ),
);

Esto nos permitirá ordenar por un campo llamado 'name', y ordenar en orden descendiente cuando se pulse sobre la cabecera.

Ahora se requiere añadir la ordenación de las tablas SQL a nuestra SQL original:

$sql = "SELECT id, name, state, customer, creator FROM {[table]}";
// añadir el orden mediante la cláusula
$sql .= tablesort_sql ( $headers );

Ahora le pasamos esto a nuestra llamada a pager_query y bingo, tenemos una tabla ordenable, paginada y con opciones extra.

Aún más lejos

La belleza de Drupal es que puede llegar tan lejos como quiera. Una opción obvia es añadirle la funcionalidad de Arrastrar y Soltar, o envolverlo en una función theme, de manera que todo el código se añada a una página con con una llamada a su propia función de tema, como por ejemplo theme ( 'paged_table', $data );.

Por favor, hágame saber si lo encuentra útil o si ha llegado más lejos.

En futuras semanas iré comentando cómo definir sus propios elementos personalizables como mencioné más arriba.

¡Feliz codificación!

N.T.

En el código, los literales se han mantenido en inglés. Así lo recomienda la gente de Drupal, ya que el inglés es el idioma oficial de Drupal. Las traducciones al resto de idiomas se realizarán todas de la misma manera, con el inglés como base.


Comentarios

Comments powered by Disqus