Создание типа поля в модуле 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;
Аннотация над классом внутри комментария к документу должна включать уникальный идентификатор, метку и средство форматирования по умолчанию. Форматтер по умолчанию будет идентификатором, используемым в аннотации класса форматера поля.
/**
 * 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 contains the values that the field will store
    'columns' => array(
      // List the values that the field will save. This
      // field will only save a single value, 'value'
      'value' => array(
        'type' => 'text',
        'size' => 'tiny',
        'not null' => FALSE,
      ),
    ),
  );
}
Этот метод возвращает массив спецификаций столбцов API схемы.
Метод 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(), чтобы установить значения по умолчанию
 - Создайте схему конфигурации для созданных вами настроек
 - Создайте форму, чтобы позволить пользователям изменять настройки
 
Шаг 1: переопределить FieldItemBase::defaultFieldSettings()
/**
 * {@inheritdoc}
 */
public static function defaultFieldSettings() {
  return [
    // Declare a single setting, 'size', with a default
    // value of 'large'
    'size' => 'large',
  ] + parent::defaultFieldSettings();
}
Шаг 2. Создайте схему конфигурации для созданных вами настроек
Схема конфигурации идет в следующем файле:
[MODULE ROOT]/config/schema/[MODULE_NAME].schema.yml
В этом файле вы опишите тип (ы) данных настроек, которые вы создали в defaultFieldSettings():
Шаг 1 создал параметр с именем «size», в котором хранится строковое значение. Схема для этого будет выглядеть следующим образом:
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 = [];
  // The key of the element should be the setting name
  $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 из модуля 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;
  }
}