在 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;
}
}