Pasar al contenido principal

Creación de fields

Creando fields propios podemos definir una estructura propia en nuestro Drupal, permitiéndonos guardar los datos de una forma más semántica. También estamos mejorando el rendimiento de la página cuando creamos un field con varios campos, ya que si quisieramos hacer los mismos fields con los fields que trae Drupal por defecto, el número de tablas podría resultar bastante grande.

Para crear un field disponemos de los siguientes hooks:

  • hook_field_schema
  • hook_field_info
  • hook_field_is_empty
  • hook_field_validate
  • hook_field_settings_form
  • hook_field_instance_settings_form
  • hook_field_widget_info
  • hook_field_widget_form
  • hook_field_formatter_info
  • hook_field_formatter_view
  • hook_field_formatter_info
  • hook_field_presave

Hooks necesarios

Estructura de datos del field (hook_field_schema)

Para que cada vez que se cree un field se creen las tablas correspondientes en la base de datos, debemos de declarar el hook_field_schema definiendo las columnas de nuestro field.

Información del field ( hook_field_info() ) :

Para empezar, debemos de declarar el hook_field_info, indicando las propiedades principales del field. Este hook debe de devolver uno o varios arrays con las características principales del field, que son:

  • label: Nombre que se vera al elegir el field
  • description : Descripción del field
  • default_widget : Nombre del widget por defecto con el que se rellenará el field.
  • default_formatter : Nombre del fomatter por defecto con el que se visualizará el field.

 

Ejemplo:

function myfield_field_info() {
  return array(
    'myfield'  => array(
      'label'             =>  t('Field Label'),
      'description'       =>  'Field description',
      'default_widget'    =>  'myfield_widget',
      'default_formatter' =>  'myfield_formatter',
    )
  );
}

Configuración del field.

Existen diversos hooks que permiten crear formularios para poder configurar cada field que se crea.

hook_field_settings_form($field, $instance, $has_data)

Con este hook podemos crear un formulario para la configuración principal del field. Está configuración no debería de cambiar una vez ya hayan datos introducidos.Para ello, existe la variable $has_data que indica si se han introducido datos. Variables

hook_field_instance_settings_form($field, $instance)

Con este hook podemos crear un formulario para la configuración de la instancia del field. Debe de contener configuración que pueda cambiar con el tiempo. Variables

  1. $field; datos del field. Incluye la configuración actual (settings) del field
  2. $instance; datos del field. Incluye la configuración actual(instance_settings) de la instancia.
  3. $field; datos del field.

Widget

Para poder rellenar el field hace falta crear un widget , el cual contendrá los elementos de formulario necesaros.

hook_field_widget_info()

Este hook debe devolver un array asociativo con los widgets que tiene el módulo. Cada widget se puede asociar a cualquier field que exista. Propiedades:

  • label: Nombre del widget
  • field_types Tipos de field para los que está disponible el widget
  • behaviours; array asociativo donde indicas los comportamientos del field. Puedes indicar los siguientes valores:
    • multiple values: FIELD_BEHAVIOR_DEFAULT (soporta un solo tipo de valor(checkbox, texfield)), o FIELD_BEHAVIOUR_CUSTOM (soporta varios tipos de valor)
    • default values: FIELD_BEHAVIOR_DEFAULT (soporta valores por defecto), o FIELD_BEHAVIOUR_NONE (no hay valores por defecto)

 

Ejemplo:

function myfield_field_widget_info() {
  return array(
    'myfield_widget' => array(
      'label'             => t('My fiedl'),
      'field types'       => array('myfield'),
      'behaviours'        => array(
        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
      ),
    ),
 }

Aquí definimos el elemento de formulario por el que se compondrá el widget. A diferencía de los otros formularios, aquí se incluyen todos los datos del field,

hook_field_formatter_info()

Este hook debe devolver un array con los formatters disponibles, indicando los fields que pueden utilizarlo. A cada formater se le pueden asociar diversos displays del field.

 

Ejemplo:

function my_field_field_formatter_info() {
  return array(
    'myfield_default' => array(
      'label'           => t('Tax'),
      'field types'     => array('myfield_formatter'),
    ),
  );
}

Validación

Para que se pueda guardar el field deben de existir 2 hooks:

hook_field_is_empty($item, $field)

Este hook debe devolver TRUE o FALSE dependiendo de si el widget rellenado cumple las condiciones para determinar que se han rellenado las partes importantes.

hook_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors)

Este hook comprueba si se han rellenado correctamente los fields. Si hay algun fallo, debes de darle un valor a $errors dando una descripción del error. Ejemplo:

function myfield_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
//Recorremos todos los fields rellenados de ese tipo en la entidad.
  foreach ($items as $delta => $item) {
    if  (strlen$item['data'] >= 100) {
      $errors[$field['field_name']][$langcode][$delta][] = array(
        'error'   => 'data_long',
        'message' => t('The data is too long!'),
      );
    }
  }
}

Guardado

Disponemos del hook_field_presave con el que podemos hacer un guardado propio del field. Ejemplo:

function myfield_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  foreach ($items as $delta => $value) {
    $items[$delta] = array(
      'tax_type'  => $value['value'] * 50,
    );
  }
}

Display

hook_field_formatter_view

Devuelve un array con los posibles displays de un field. En este array se incluye el tema que procesa el field, y los datos del field. Ejemplo:

Variables:

function myfield_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $elements = array();
  foreach ($items as $delta => $item) {
    $elements[$delta] = array(
      '#theme'   => 'formatter_' . $display['type'],
      '#element' => $item,
      '#field'   => $instance,
      '#display' => $display,
    );
  }
  return $elements;
}

Integración con Entity API

Para que la Entity API pueda reconocer los datos que contiene el field debemos de hacer los siguientes cambios:

  1. En el hook_field_info(), añadir las siguientes propiedades:
    • property_type: Nombre de la propiedad asociada al field.
    • property_callbacks: Funciones a las que se llamará para ajustar la información de la propiedad al field en cuestión.
       

    Ejemplo de property_callback:


function myfield_property_info_callback(&$info, $entity_type, $field, $instance, $field_type) {
  $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$field['field_name']];
  $property['getter callback'] = 'entity_metadata_field_verbatim_get';
  $property['setter callback'] = 'entity_metadata_field_verbatim_set';

  // Auto-create the field item as soon as a property is set.
  $property['auto creation'] = 'myfield_item_create';
//Field properties
  $property['property info'] = myfield_field_item_property_info();
  $property['property info']['type']['required'] = TRUE;
  unset($property['query callback']);
}

function myfield_item_create() {
  return array(
    'type'        =>  NULL,
    'name'        =>  NULL,
    'distance'    =>  NULL,
    'timedriving' =>  NULL,
    'timewalking' =>  NULL,
  );
}

/**
 * Defines info for the properties of the link-field item data structure.
 */
function myfield_field_item_property_info() {
  $properties['type'] = array(
    'type' => 'text',
    'label' => t('Service type.'),
    'setter callback' => 'entity_property_verbatim_set',
  );
  
  $properties['name'] = array(
    'type' => 'text',
    'label' => t('Service name.'),
    'setter callback' => 'entity_property_verbatim_set',
  );
  
  $properties['distance'] = array(
    'type' => 'float',
    'label' => t('Service distance.'),
    'setter callback' => 'entity_property_verbatim_set',
  );
  
  $properties['timedriving'] = array(
    'type' => 'float',
    'label' => t('Service timedriving.'),
    'setter callback' => 'entity_property_verbatim_set',
  );
  
  $properties['timewalking'] = array(
    'type' => 'float',
    'label' => t('Service timewalking.'),
    'setter callback' => 'entity_property_verbatim_set',
  );
  return $properties;
}
Omar Lopesino

Omar Lopesino

Senior Drupal developer