Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Определение и использование определений Content Entity Field

17/05/2020, by maria

Content entities должны явно определять все свои поля, предоставляя определения для класса entities. Определения полей основаны на Typed data API (см., Как сущности реализуют его).

Определения полей

Типы сущностей определяют свои базовые поля в статическом методе класса сущностей. Базовые поля - это не настраиваемые поля, которые всегда существуют в данном типе сущности, например, название узла или даты создания и изменения. Менеджер сущностей дополняет поля настраиваемыми и неконфигурируемыми полями, предоставляемыми другими модулями, вызывая hook_entity_field_info() и hook_entity_field_info_alter(). Это также, как поля, сконфигурированные через Field UI, также добавляются (эти хуки больше не существуют в соответствии с API).

Определения полей являются простыми объектами, реализующими FieldDefinitionInterface, тогда как базовые поля обычно создаются с помощью класса BaseFieldDefinition, а настраиваемые поля напрямую реализуют интерфейс с соответствующими объектами конфигурации (так называемыми Field и FieldInstance).
Определения полей также являются местом для определения проверочных ограничений для элементов поля или свойств элемента поля. Могут быть использованы все реализации плагина типа поля. (Этот интерфейс и класс больше не существуют).

Поля в настоящее время всегда являются списком элементов поля, что означает, что класс FieldItem, определенный как тип, будет заключен в класс FieldItemList, представляющий список этих элементов поля.

Все поля (включая базовые поля) также могут иметь виджеты и средства форматирования для их отображения и редактирования.

Базовые поля

Ниже приведен сокращенный примерный список определений полей типа сущности узла.

use Drupal\Core\Field\BaseFieldDefinition;

class Node implements NodeInterface {

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions($entity_type) {
    // The node id is an integer, using the IntegerItem field item class.
    $fields['nid'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Node ID'))
      ->setDescription(t('The node ID.'))
      ->setReadOnly(TRUE);

    // The UUID field uses the uuid_field type which ensures that a new UUID will automatically be generated when an entity is created.
    $fields['uuid'] = BaseFieldDefinition::create('uuid')
      ->setLabel(t('UUID'))
      ->setDescription(t('The node UUID.'))
      ->setReadOnly(TRUE);

    // The language code is defined as a language_field, which, again, ensures that a valid default language
    // code is set for new entities.
    $fields['langcode'] = BaseFieldDefinition::create('language')
      ->setLabel(t('Language code'))
      ->setDescription(t('The node language code.'));

    // The title is StringItem, the default value is an empty string and defines a property constraint for the
    // value to be at most 255 characters long.
    $fields['title'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Title'))
      ->setDescription(t('The title of this node, always treated as non-markup plain text.'))
      ->setRequired(TRUE)
      ->setTranslatable(TRUE)
      ->setSettings(array(
        'default_value' => '',
        'max_length' => 255,
      ));

    // The uid is an entity reference to the user entity type, which allows to access the user id with $node->uid->target_id
    // and the user entity with $node->uid->entity. NodeInterface also defines getAuthor() and getAuthorId(). (@todo: check owner vs. revisionAuthor)
    $fields['uid'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('User ID'))
      ->setDescription(t('The user ID of the node author.'))
      ->setSettings(array(
        'target_type' => 'user',
        'default_value' => 0,
      ));

    // The changed field type automatically updates the timestamp every time the
    // entity is saved.
    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the node was last edited.'))
    return $fields;
  }
}

Многозначные поля

Чтобы указать максимальное количество элементов, допустимое для поля, вызовите метод setCardinality().
Например, чтобы определить поле, которое может иметь 3 вызова элемента:

->setCardinality(3);

Чтобы определить поле с неограниченными значениями, позвоните:

->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);

Пример определения многозначного поля для ссылки на сущности «пользователь»:

$fields['my_field'] = BaseFieldDefinition::create('entity_reference')
  ->setLabel(t('The label of the field'))
  ->setDescription(t('The description of the field.'))
  ->setRevisionable(TRUE)
  ->setSetting('target_type', 'user')
  ->setSetting('handler', 'default')
  ->setTranslatable(TRUE)
  ->setDisplayOptions('view', [
    'label' => 'hidden',
    'type' => 'author',
    'weight' => 0,
  ])
  ->setDisplayOptions('form', [
    'type' => 'entity_reference_autocomplete',
    'weight' => 5,
    'settings' => [
      'match_operator' => 'CONTAINS',
      'size' => '60',
      'autocomplete_type' => 'tags',
      'placeholder' => '',
    ],
  ])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);
  ->setRequired(TRUE)
  ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);

Сущность также может предоставлять поля, которые существуют только для определенного пакета, или изменять их с помощью пакета. Например, заголовок узла может иметь различную метку для каждого пакета. Чтобы обеспечить изменения в пакете, определение базового поля должно быть клонировано до внесения изменений, так как в противном случае это изменило бы определение базового поля и затронуло бы все пакеты.

use Drupal\node\Entity\NodeType;

  /**
   * {@inheritdoc}
   */
  public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
    $node_type = NodeType::load($bundle);
    $fields = array();
    if (isset($node_type->title_label)) {
      $fields['title'] = clone $base_field_definitions['title'];
      $fields['title']->setLabel($node_type->title_label);
    }
    return $fields;
  }

Типы полей

Ядро Drupal предоставляет список типов полей, которые можно использовать для базовых полей. Кроме того, модули могут предоставлять дополнительные типы полей, которые также могут использоваться.

  • строка: простая строка
  • логическое значение: логическое значение, хранящееся как целое число.
  • целое число: целое число с настройками для проверки минимального и максимального значений (также предоставляется для десятичной и плавающей запятой)
  • десятичная дробь: десятичная дробь с настраиваемой точностью и масштабом.
  • float: число с плавающей точкой
  • язык: содержит код языка и язык как вычисляемое свойство
  • отметка времени: отметка времени Unix, хранящаяся как целое число
  • созданный: отметка времени, которая использует текущее время в качестве значения по умолчанию.
  • изменено: временная метка, которая автоматически обновляется до текущего времени, если объект сохраняется.
  • datetime: дата хранится в виде строки ISO 8601.
  • URI: содержит URI. Модуль связи также предоставляет тип поля ссылки, который может включать заголовок ссылки и может указывать на внутренний или внешний URI / маршрут.
  • uuid: поле UUID, которое генерирует новый UUID в качестве значения по умолчанию.
  • электронная почта: электронная почта с соответствующей проверкой, виджетами и форматерами.
  • entity_reference: ссылка на сущность с помощью target_id и свойства поля вычисляемой сущности. entity_reference.module предоставляет виджеты и форматеры, когда они включены.
  • карта: может содержать любое количество произвольных свойств, хранящихся в виде сериализованной строки

Настраиваемые поля

Дополнительные поля могут быть зарегистрированы в hook_entity_base_field_info() и hook_entity_bundle_field_info(). В следующих примерах добавляются поля base и bundle.

use Drupal\Core\Field\BaseFieldDefinition;

/**
 * Implements hook_entity_base_field_info().
 */
function path_entity_base_field_info(EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'taxonomy_term' || $entity_type->id() === 'node') {
    $fields['path'] = BaseFieldDefinition::create('path')
      ->setLabel(t('The path alias'))
      ->setComputed(TRUE);

    return $fields;
  }
}

/**
 * Implements hook_entity_bundle_field_info().
 */
function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
  if ($entity_type->isFieldable()) {
    // Configurable fields, which are always attached to a specific bundle, are
    // added 'by bundle'.
    return Field::fieldInfo()->getBundleInstances($entity_type->id(), $bundle);
  }
}

Соответствующие alter hooks существуют для каждого из вышеперечисленных.

Хранение файлов

Если у вашего поля нет особых требований, API Entity Field может позаботиться о хранении базы данных и соответствующим образом обновить схемы базы данных. Это значение по умолчанию для полей, которые не помечены как вычисляемые поля (setComputed(TRUE)) или специально указали для предоставления собственного хранилища полей (setCustomStorage(TRUE)).

Допустим, вы хотите добавить новое базовое поле для всех сущностей Node, которое содержит простое логическое значение, чтобы указать, выделено ли содержимое.

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;

/**
 * Implements hook_entity_base_field_info().
 */
function MYMODULE_entity_base_field_info(EntityTypeInterface $entity_type) {
  $fields = array();

  // Add a 'Highlight' base field to all node types.
  if ($entity_type->id() === 'node') {
    $fields['highlight'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Highlight'))
      ->setDescription(t('Whether or not the node is highlighted.'))
      ->setRevisionable(TRUE)
      ->setTranslatable(TRUE)
      ->setDisplayOptions('form', array(
        'type' => 'boolean_checkbox',
        'settings' => array(
          'display_label' => TRUE,
        ),
      ))
      ->setDisplayConfigurable('form', TRUE);
  }

  return $fields;
}

Я пробовал так много раз, и посещение update.php не добавит столбец в базу данных, но запустит

  \Drupal::entityTypeManager()->clearCachedDefinitions();
  \Drupal::service('entity.definition_update_manager')->applyUpdates();

может иметь столбец, созданный в базе данных. Примечание: при этом также будут запускаться любые обновления, которые могут быть ожидающими для других определений полей.

Обновление: код выше не будет работать с Drupal 8.7

Смотрите пример из этой записи об изменениях

Установка нового определения хранилища полей

function example_update_8701() {
  $field_storage_definition = BaseFieldDefinition::create('boolean')
    ->setLabel(t('Revision translation affected'))
    ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
    ->setReadOnly(TRUE)
    ->setRevisionable(TRUE)
    ->setTranslatable(TRUE);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('revision_translation_affected', 'block_content', 'block_content', $field_storage_definition);
}

Если ваш пользовательский модуль добавляет новое поле, оно будет добавлено автоматически при включении модуля и удалено при удалении модуля.

Если ваш модуль уже установлен, и вам нужно написать hook_update_N для обновления определений полей, вы можете сделать что-то вроде:

/**
 * Add in highlight field to all nodes.
 */
function MYMODULE_update_8001() {
  $entity_type = \Drupal::service('entity_type.manager')->getDefinition('node');
  \Drupal::service('entity.definition_update_manager')->updateEntityType($entity_type);
}

или

/**
 * Add 'revision_translation_affected' field to 'node' entities.
 */
function node_update_8001() {
  // Install the definition that this field had in
  // \Drupal\node\Entity\Node::baseFieldDefinitions()
  // at the time that this update function was written. If/when code is
  // deployed that changes that definition, the corresponding module must
  // implement an update function that invokes
  // \Drupal::entityDefinitionUpdateManager()->updateFieldStorageDefinition()
  // with the new definition.
  $storage_definition = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Revision translation affected'))
      ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
      ->setReadOnly(TRUE)
      ->setRevisionable(TRUE)
      ->setTranslatable(TRUE);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('revision_translation_affected', 'node', 'node', $storage_definition);
}

См. Https://www.drupal.org/node/2554097 для получения дополнительной информации и примеров.

Работа с определениями полей

Примечание. Поскольку объекты являются сложными данными, они должны следовать за ComplexDataInterface. С точки зрения типизированных данных все содержащиеся типизированные элементы данных в сложном объекте данных являются свойствами. Это ограничение / обязательное присвоение имен может быть снято.

// Checks whether an entity has a certain field.
$entity->hasField('field_tags');

// Returns an array with named keys for all fields and their
// definitions. For example the ‘image’ field.
$field_definitions = $entity->getFieldDefinitions();

// Returns an array with name keys for all field item properties and their
// definitions of the image field. For example the ‘file_id’ and ‘alt’ properties.
$property_definitions = $entity->image->getFieldDefinition()->getPropertyDefinitions();

// Returns only definition for the ‘alt’ property.
$alt_definition = $entity->image->getFieldDefinition()->getPropertyDefinition('alt');

// Entity field definitions can also be requested from the entity manager,
// the following returns all fields that are available for all bundles.
\Drupal::service('entity_field.manager')->getFieldStorageDefinitions($entity_type);

// The following returns fields that are available for the given bundle.
\Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type, $bundle);

Виджеты и форматеры для базовых полей

Базовые поля могут указывать виджеты и средства форматирования, которые они должны использовать, как настраиваемые поля. Виджет и средство форматирования и необходимые параметры задаются в классе FieldDefinition следующим образом:

use Drupal\Core\Field\BaseFieldDefinition;

// ...

    $fields['title'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Title'))
      ->setDescription(t('The title of this node, always treated as non-markup plain text.'))
      ->setRequired(TRUE)
      ->setTranslatable(TRUE)
      ->setSettings(array(
        'default_value' => '',
        'max_length' => 255,
      ))
      ->setDisplayOptions('view', array(
        'label' => 'hidden',
        'type' => 'string',
        'weight' => -5,
      ))
      ->setDisplayOptions('form', array(
        'type' => 'string',
        'weight' => -5,
      ))
      ->setDisplayConfigurable('form', TRUE);

При этом используются формататор «string» и виджет, а также настраивается вес для заголовка узла. setDisplayConfigurable() может использоваться, чтобы сделать поле видимым в пользовательском интерфейсе управления отображением формы/управления, чтобы можно было изменить порядок и отображение ярлыков. В настоящее время ядро не позволяет изменять виджет или их настройки в пользовательском интерфейсе.

Для установки поля как скрытого по умолчанию вы также можете определить ключ региона в массиве, который вы передаете setDisplayOptions(), и установить его в скрытый.

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.