在 Drupal 模块中创建字段类型
字段类型定义了字段的属性和行为。字段类型被定义为插件,因此在编写新的字段类型之前,建议先熟悉 插件 API。
在 Drupal 8 中创建字段类型,需要一个带有 FieldType 注解的类。
类的位置 应放在 MODULE_NAME/src/Plugin/Field/FieldType
例如:/modules/foo/src/Plugin/Field/FieldType/BazItem.php
类的命名空间 应该是 Drupal\MODULE_NAME\Plugin\Field\FieldType
<?php namespace Drupal\MODULE_NAME\Plugin\Field\FieldType;
类上的注解必须包含唯一的 ID、标签以及默认的格式化器和小部件。默认的格式化器 ID 应与字段格式化器类注解中定义的 ID 一致。
/** * Provides a field type of baz. * * @FieldType( * id = "baz", * label = @Translation("Baz field"), * default_formatter = "baz_formatter", * default_widget = "baz_widget", * ) */
类必须实现 FieldItemInterface,并且应扩展 FieldItemBase 以获得通用实现。
class BazItem extends FieldItemBase { }
必须重写 FieldItemInterface::schema() 来告诉系统如何存储字段值。
/** * {@inheritdoc} */ public static function schema(FieldStorageDefinitionInterface $field_definition) { return array( // columns 包含字段将存储的值 'columns' => array( // 本字段只保存一个值 'value' 'value' => array( 'type' => 'text', 'size' => 'tiny', 'not null' => FALSE, ), ), ); }
该方法返回 API schema 列定义数组。
方法 FieldItemInterface::propertyDefinitions() 提供关于字段属性的详细信息:
/** * {@inheritdoc} */ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties = []; $properties['value'] = DataDefinition::create('string'); return $properties; }
还需要重写 Map::isEmpty()(FieldItemBase 的父类)来定义字段何时为空。
/** * {@inheritdoc} */ public function isEmpty() { $value = $this->get('value')->getValue(); return $value === NULL || $value === ''; }
字段设置
字段设置允许用户根据需求配置字段。如果字段有设置,需要完成以下三步:
- 重写 FieldItemBase::defaultFieldSettings() 来设置默认值
- 为这些设置定义配置 schema
- 创建表单让用户修改设置
步骤 1: 重写 FieldItemBase::defaultFieldSettings()
/** * {@inheritdoc} */ public static function defaultFieldSettings() { return [ // 声明一个 'size' 设置,默认值为 'large' 'size' => 'large', ] + parent::defaultFieldSettings(); }
步骤 2: 定义配置 schema
配置 schema 文件路径:
[MODULE ROOT]/config/schema/[MODULE_NAME].schema.yml
描述在 defaultFieldSettings() 中定义的设置的数据类型:
field.field_settings.[FIELD ID]: type: mapping label: 'FIELDNAME settings' mapping: size: type: string label: 'Size'
步骤 3: 创建表单让用户修改设置
通过重写 FieldItemBase::fieldSettingsForm() 创建表单:
/** * {@inheritdoc} */ public function fieldSettingsForm(array $form, FormStateInterface $form_state) { $element = []; // 元素的 key 必须与设置名一致 $element['size'] = [ '#title' => $this->t('Size'), '#type' => 'select', '#options' => [ 'small' => $this->t('Small'), 'medium' => $this->t('Medium'), 'large' => $this->t('Large'), ], '#default_value' => $this->getSetting('size'), ]; return $element; }
实际示例
RgbItem 示例来自 Examples 模块 的 field_example:
namespace Drupal\field_example\Plugin\Field\FieldType; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; /** * Plugin implementation of the 'field_example_rgb' field type. * * @FieldType( * id = "field_example_rgb", * label = @Translation("Example Color RGB"), * module = "field_example", * description = @Translation("Demonstrates a field composed of an RGB color."), * default_widget = "field_example_text", * default_formatter = "field_example_simple_text" * ) */ class RgbItem extends FieldItemBase { /** * {@inheritdoc} */ public static function schema(FieldStorageDefinitionInterface $field_definition) { return array( 'columns' => array( 'value' => array( 'type' => 'text', 'size' => 'tiny', 'not null' => FALSE, ), ), ); } /** * {@inheritdoc} */ public function isEmpty() { $value = $this->get('value')->getValue(); return $value === NULL || $value === ''; } /** * {@inheritdoc} */ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties['value'] = DataDefinition::create('string') ->setLabel(t('Hex value')); return $properties; } }