9.10. API de campos de Drupal. Campos de Drupal en la base de datos.
En este artículo vamos a entender cómo funcionan los campos en Drupal, para qué sirven y cómo los campos ayudan a desarrollar sitios en Drupal de manera rápida.
Ya hemos trabajado con campos en artículos anteriores:
7.5. Maquetar el bloque de servicios con columnas de Bootstrap
7.6. Galería Isotope para Drupal
7.7. Bloque con video de YouTube en Drupal
Ahora vamos a entender cómo funciona. Vamos a editar los campos del tipo de contenido Artículo y añadir un nuevo campo de tipo Enlace:
/admin/structure/types/manage/article/fields
Al crear un nuevo artículo, verás dos campos de entrada para URL y texto del enlace:
Cada vez que creas un campo nuevo desde la administración, Drupal crea dos tablas en la base de datos:
{entity_type}__{field_name}
{entity_type}_revision__{field_name}
Drupal admite revisiones, por lo que todos los datos se duplican al menos una vez, siendo la única revisión la versión actual de tu artículo. Así, los campos y toda la API de campos de Drupal sirven para simplificar el trabajo con la base de datos. Creamos campos desde la administración y Drupal crea las tablas automáticamente.
Por el nombre de las tablas MySQL debería quedar claro que un mismo campo se puede usar para un solo tipo de entidad. Por ejemplo, ahora podemos usar el campo Enlace en el contenido del tipo Página básica como ya existente:
/admin/structure/types/manage/page/fields/add-field
Pero si deseas crear un campo Enlace en un bloque, deberás crear uno nuevo. No es posible usar el mismo campo en entidades de tipo diferente. Creamos un campo Enlace para el tipo de bloque Básico:
/admin/structure/block/block-content/manage/basic/fields/add-field
Como puedes ver, al crear el campo no aparece la opción de elegir el campo Enlace existente, porque Bloque y Nodo son tipos de entidad diferentes.
Y como ocurre con los nodos, se crean dos tablas para guardar los datos del campo Enlace para los bloques:
block_content_revision__field_link y block_content__field_link.
Ahora vamos a entender cómo almacena Drupal los datos del mismo campo para diferentes bundles. Creamos el campo Enlace para el tipo de nodo Artículo, pero luego reutilizamos este campo en el tipo de nodo Página básica. Para facilitarlo, es mejor exportar la configuración del sitio a una carpeta y ver los archivos, aunque también se puede revisar desde adminer o phpmyadmin en la tabla config:
Si buscas todas las configuraciones que contengan la palabra "link":
SELECT * FROM `config` WHERE CONVERT(`name` USING utf8mb4) LIKE '%link%' LIMIT 50
Encontraremos las siguientes configuraciones para nuestro campo field_link:
- field.field.block.block_content.basic.field_link
- field.field.node.article.field_link
- field.field.node.page.field_link
- field.storage.block_content.field_link
- field.storage.node.field_link
Para cada tipo de entidad, se crea su propia configuración Field Storage. Esta configuración define cómo se almacenan los datos en las tablas {entity_type}__{field_name} y {entity_type}_revision__{field_name}. En nuestro caso: node__field_link, block_content__field_link, etc. Veamos cómo el módulo Link guarda los datos. Abramos la configuración Field Storage para el campo Link:
uuid: dba847ef-f4d6-4462-a2ee-f642a007fca6
langcode: en
status: true
dependencies:
module:
- block_content
- link
id: block_content.field_link
field_name: field_link
entity_type: block_content
type: link
settings: { }
module: link
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
Explicación de los valores más relevantes:
- uuid: ID único de la configuración.
- langcode: Idioma predeterminado.
- status: Indica si la configuración está habilitada.
- dependencies: Dependencias de los módulos requeridos.
- field_name: Nombre máquina del campo, usado en el código como
$node->field_link->uri
. - entity_type: Tipo de entidad al que pertenece.
- type: Tipo de campo, en este caso
link
. - settings: Configuración personalizada (vacía por ahora).
- cardinality: Número de valores permitidos.
- translatable: Indica si es traducible.
- indexes: Índices adicionales para mejorar el rendimiento.
- custom_storage: Si se usa almacenamiento personalizado.
Si revisamos el archivo del tipo de campo:
core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
En el método propertyDefinitions()
veremos los campos almacenados:
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['uri'] = DataDefinition::create('uri')
->setLabel(t('URI'));
$properties['title'] = DataDefinition::create('string')
->setLabel(t('Link text'));
$properties['options'] = MapDataDefinition::create()
->setLabel(t('Options'));
return $properties;
}
Estos datos corresponden a los campos que se guardan en la tabla node__field_link:
Así, con la Fields API de Drupal creamos un tipo de campo a través de una clase en PHP, como LinkItem
. Esto nos permite crear un campo para entidades, ingresar datos y almacenarlos en la base de datos. La API también configura el formulario de entrada y salida del campo.
Al crear el campo para Artículo y Página básica, generamos una única configuración para Field Storage: field.storage.node.field_link.yml
, pero también una configuración por bundle:
- field.field.node.article.field_link.yml
- field.field.node.page.field_link.yml
- field.field.block.block_content.basic.field_link.yml
Estas configuraciones almacenan los ajustes del formulario de entrada:
Por lo tanto, podemos personalizar la entrada de datos del campo de forma distinta para cada bundle. Cada una de estas configuraciones se denomina Instancia de campo (Field Instance). En Drupal 8 ya no hay funciones específicas para Field Instances; ahora todo se gestiona mediante la CRUD API:
https://www.drupal.org/node/2054619
Ejemplos de cómo trabajar con campos mediante código están disponibles en la documentación oficial:
https://www.drupal.org/node/2012896
En este artículo solo vimos la parte de almacenamiento de datos. En las siguientes lecciones veremos cómo funciona la entrada y salida de datos con la Fields API, y crearemos nuestro propio tipo de campo personalizado.