Extra fields (также известны как Pseudo Fields, псевдо-поля, экстра-поля) — дополнительные поля используемые в «Управлении отображением» той или иной сущности, позволяющие добавлять любую дополнительную информацию в процессе рендера.
По умолчанию в Drupal все добавленные поля к сущности имеют возможность настройки отображения и их рендера. Псевдо-поля позволяют генерировать своё содержимое на лету, и являются частью процесса рендера. Они могут быть подключены как к рендеру результата, так и к форме создания/редактирования сущности.
Псевдо-поля не имеют ни настроек, ни поддержки виджетов, как и не могут их добавлять. То что будет выведено, полностью зависит от самого псевдо-поля на основе предоставленнымх ему данных. Если вы хотите сделать виртуальное поле без хранения данных в БД, но с поддержкой виджетов, то вам следует обратить своё внимание на вычисляемые поля.
Управлять отображением псевдо поля можно через стандартный административный интерфейс, но для модификации будет доступен вес и видимость поля.
¶hook_entity_extra_field_info()
Для того чтобы объявить своё псевдо-поле, необходимо реализовать хук hook_entity_extra_field_info()
. Хук должен вернуть массив из значений, которые могут содержать следующие ключи:
-
label
: Человекопонятная метка для данного поля. Отображается в административном интерфейсе. -
description
: Описание поля, по умолчанию нигде не отображается. -
weight
: Вес псевдо-поля в «Управлении отображением» по умолчанию. -
visible
: (опционально) Логическое значение, будет ли данное поле по умолчанию отображаться или скрыто. Значение по умолчаниюTRUE
— поле будет сразу выводиться. -
edit
: (опционально) Позволяет задать разметку, которая будет отображаться на странице «Управление содержимым». Работает только для контекстаform
. -
delete
: (опционально) Позволяет задать разметку, которая будет отображаться на странице «Управление содержимым». Работает только для контекстаform
.
Значения псевдо-полей должны находиться в структуре массива по следующему паттерну: $fields[{entity_type_id}][{bundle_id}][{extra_field_type}][{extra_field_name}]
, где:
-
{entity_type_id}
: Машинное имя сущности для которого добавляется данное псевдо-поле. -
{bundle_id}
: Подтип сущности для которого добавляется данное псевдо-поле. -
{extra_field_type}
: Тип псевдо-поля, может быть одним из двух значений:-
display
: Данные псевдо-поля доступны при выводе материала. -
form
: Данные псевдо-поля доступны в формах редактирования материала.
-
-
{extra_field_name}
: Машинное имя псевдо-поля которое будет использовано в качестве ключа для хранения в отображении.
¶Пример псевдо-поля типа display
Псевдо-поля типа display
выводятся в момент рендера материала. Для их вставки используется хук hook_view()
и его аналоги.
Пример добавления псевдо-поля с обычной строкой к «Типу содержимого» (сущность node) «Новость» (news):
/**
* Implements hook_entity_extra_field_info().
*/
function example_entity_extra_field_info() {
$extra = [];
$extra['node']['news']['display']['extra_foo_bar'] = [
'label' => new TranslatableMarkup('Foo bar field'),
'description' => new TranslatableMarkup('Prints "foo bar" string.'),
'weight' => 3,
];
return $extra;
}
/**
* Implements hook_ENTITY_TYPE_view().
*/
function example_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
if ($display->getComponent('extra_foo_bar')) {
$build['extra_foo_bar'] = [
'#type' => 'markup',
'#markup' => 'foo bar',
];
}
}
¶Пример псевдо-поля типа form
Псевдо-поля типа form
выводятся в форме редактирования/создания материала. Для их вставки используется хук hook_form_alter()
и его аналоги.
Пример добавления псевдо-поля с валидацией его значения к «Типу содержимого» (сущность node) «Новость» (news). Данное поле будет ожидать что в него введут foo bar
, иначе оно будет запрещать отправку формы.
/**
* Implements hook_entity_extra_field_info().
*/
function example_entity_extra_field_info() {
$extra = [];
$extra['node']['news']['form']['extra_foo_bar'] = [
'label' => new TranslatableMarkup('Foo bar field'),
'description' => new TranslatableMarkup('Enter "foo bar" to continue.'),
'weight' => 3,
];
return $extra;
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function example_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$storage = $form_state->getStorage();
if (!empty($storage['form_display']) && $storage['form_display'] instanceof EntityFormDisplay) {
$form_display = $storage['form_display'];
if ($component = $form_display->getComponent('extra_foo_bar')) {
$form['extra_foo_bar'] = [
'#type' => 'textfield',
'#title' => new TranslatableMarkup('Foo bar field'),
'#default_value' => new TranslatableMarkup('Enter "foo bar" to continue.'),
'#required' => TRUE,
'#weight' => $component['weight'],
];
$form['#validate'][] = 'example_foo_bar_validation';
}
}
}
/**
* Validates 'extra_foo_bar' extra field.
*/
function example_foo_bar_validation(&$form, FormStateInterface $form_state) {
if ($form_state->getValue('extra_foo_bar') != 'foo bar') {
$form_state->setError($form['extra_foo_bar'], new TranslatableMarkup('Enter "foo bar" to proceed.'));
}
}
¶Расширения
-
Extra Field — добавляет возможность объявлять псевдо-поля типа
display
при помощи плагинов. Рекомендуется к использованию вместо хуков, так как позволяет поддерживать код в чистоте и более организованно.
¶Изменения в релизах
- Drupal 9.1.0 (02.12.2020): Исправлена неполадка, из-за которой псевдо-поля не рендерились при выводе содержимого через Layout Builder.
¶Ссылки
- Drupal 8: Создание псевдо-полей (Extra Fields), Niklan, 2018
- Сравнение производительности различных способов вывода псевдо полей, xandeadx.ru, 2021