Hero

Como utilizar tablas personalizadas en Views con Drupal 7

Mayo 09, 2014

enzo
Drupal
Desarrollo de Modulos
Vistas

Como ya hemos visto en las entrada de blog Como crear tablas para nuestros módulos personalizados en Drupal 7 y Como agregar una nueva tabla a modulo ya activado en Drupal 7 es posible la creación de un modelo de datos personalizado en la base de datos que guarde cierta relación con el modelo de datos de Drupal.

Para poder aprovechar todos el potencial de Drupal es necesario poder usar nuestros datos en conjunto con el modulo de Views, afortunadamente Views tiene un API que nos permite realizar está funcionalidad por medio del hook hook_views_data() que vamos a detallar a continuación.

  1. Definir tabla.

Siguiendo las entradas de blog antes mencionada creamos nuestra tabla personalizada, como se muestra a continuación.

$schema['orders'] = array(
    'mysql_engine' => 'INNODB',
    'description' => 'The base table for orders',
    'fields' => array(
      'oid' => array(
        'description' => 'The primary identifier for a order.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the order was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'total' => array(
        'description' => 'The sum of order lines calculated by price X quantity.',
        'type' => 'float',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'uid' => array(
        'description' => 'The {users}.uid customer that owns this order.',
        'type' => 'int',
        'length' => 10,
        'not null' => TRUE,
        'default' => 0,
      ),
      'vid' => array(
         'type' => 'int', 
         'unsigned' => TRUE, 
         'not null' => TRUE, 
         'default' => 0
      ),
      'nid' => array(
         'type' => 'int', 
         'unsigned' => TRUE, 
         'not null' => TRUE, 
         'default' => 0
      ), 
    ),
    'indexes' => array(
       'uid' => array('uid'),
      ),
    'foreign keys' => array(
      'order_author' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
     ),
    'primary key' => array('oid'),
  );

La tabla anterior define una orden que esta vinculada a algún nodo por medio de los campos nid y vid, el proceso de creación de la orden y como se vinculan con el nodo esta fuera del alcance de esta entrada de blog.

  1. Definir table en Views.

Ahora debemos informarle al modulo de Views que nuestra tabla existe usando el siguiente modulo.

/**
 * Implements hook_views_data().
 */
function MIMODULO_views_data() {
  $data = array();

  // Make the node_revision_states table available for node and node revision
  // views.
  $data['orders']['table']['group'] = t('Orders);
 
  // Define tables relationship 
  $data['orders']['table']['join']['node'] = array(
    'left_field' => 'vid',
    'field' => 'vid',
  );
  $data['orders']['table']['join']['node_revision'] = array(
    'left_field' => 'vid',
    'field' => 'vid',
  );

  // Make the state and timestamp fields available.
  $data['order]['oid'] = array(
    'title' => t('Order ID'),
    'help' => t("The order ID of the selected node's revision."),
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
    ),
    'sort' => array(
      'handler' => 'views_handler_sort',
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_numeric',
    ),
    'argument' => array(
      'handler' => 'views_handler_argument_string',
    ),
  );
  $data['orders']['created'] = array(
    'title' => t('Order Created At'),
    'help' => t("The order timestamp of the selected node's revision."),
    'field' => array(
      'handler' => 'views_handler_field_date',
      'click sortable' => TRUE,
    ),
    'sort' => array(
      'handler' => 'views_handler_sort_date',
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_date',
    ),
  );

  return $data;
} 

Existen muchas otras opciones que se pueden ver en la pagina del hook_views_data, para efectos de este ejemplo veamos algunas y las demás opciones se dejan a la necesidad del lector :P.

Veamos las opciones que se utilizaron en el ejemplo anterior y su implicación.

2.1 Definir el grupo de los campos.

Cuando estamos creando un vista y vamos a agregar campos nos aparece una forma de poder seleccionar los campos que pertenecen a este grupo como lo muestra la siguiente imagen.

views field grouping

Como se aprecia en la imagen anterior hay dos campos que pertenecen al grupo State Flow History, para crear esto usamos el siguiente código.

  // Make the node_revision_states table available for node and node revision
  // views.
  $data['orders']['table']['group'] = t('Orders);

En nuestro caso indicamos que los campos de la tabla orders pertenecen al Grupo Orders, si el grupo no existe sera agregado a la lista de disponibles de Views.

2.2. Definir relación entre tablas.

Como ya sabemos el modulo de Views se encarga de generar una consulta para traer la información requerida, en el siguiente ejemplo le indicamos a Views cual es la relación de la tabla orders con las tablas node y node_revisions.

  // Define tables relationship 
  $data['orders']['table']['join']['node'] = array(
    'left_field' => 'vid',
    'field' => 'vid',
  );
  $data['orders']['table']['join']['node_revision'] = array(
    'left_field' => 'vid',
    'field' => 'vid',
  );

El código anterior define los campos que serán usando al generar la consulta en este caso los campos vid de cada una de las tablas, cuando en una vista utilicemos algún campo del Grupo Orders se generara un Left Join en nuestro SQL.

2.3 Definir propiedades de los campos

Para terminar debemos informar a Views como se manejaran los campos, como se aprecia en el siguiente código.

  // Make the state and timestamp fields available.
  $data['order]['oid'] = array(
    'title' => t('Order ID'),
    'help' => t("The order ID of the selected node's revision."),
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
    ),
    'sort' => array(
      'handler' => 'views_handler_sort',
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_numeric',
    ),
    'argument' => array(
      'handler' => 'views_handler_argument_string',
    ),
  );

Como se puede apreciar tenemos varias propiedades intuitivas como son title y help, la propiedad field es la mas importante porque nos permite definir la función con la que sea imprimirá la información del field a las funciones que realizan acciones sobre campos se les conoce como handlres y en nuestro caso como no necesitamos nada en particular podemos utilizar el handler genérico views_handler_field.

Opcionalmente en el field podemos definir si el campo se le puede activar un ordenamiento, en caso de activar esta propiedad debemos definir un sort handler y en nuestro ejemplo volveremos a usar un handle genérico el views_handler_sort.

También podemos definir una función para el filtrado como por ejemplo views_handler_filter_numeric, así como también podemos habilitar que nuestro campo sea utilizado como un argumento y en este caso utilizando el handler genérico views_handler_argument_string.

Puedes obtener mas información acerca de views handlers en https://api.drupal.org/api/views/views.api.php/group/views_handlers/7 disponibles o es posible que crees tus propios views handlers.

Puedes ver una implementación extra que he propuesto para el módulo State Machine en el issue https://drupal.org/node/2263215#comment-8766023.

Espero que haya sido de su agrado.

Recibe consejos y oportunidades de trabajo 100% remotas y en dólares de weKnow Inc.