Плагины
Плагин — класс, который добавляет в систему ещё один вариант чего-либо: ещё один блок, ещё один способ вывести поле, ещё один фильтр текста. Блок из прошлого урока — плагин. Все плагины устроены одинаково, поэтому, поняв один вид, легко писать остальные.
Как Drupal находит плагины
У каждого вида плагинов есть три вещи:
- папка внутри
src/Plugin, где лежат классы; - атрибут с описанием: машинное имя, название;
- базовый класс с методами, которые нужно реализовать.
Регистрировать плагин в файлах YAML не нужно. При drush cr Drupal просматривает папки src/Plugin всех модулей и запоминает классы с подходящим атрибутом.
Форматтер поля
Форматтер решает, как вывести значение поля. Напишем форматтер, который вместо текста статьи показывает время чтения. Его папка — src/Plugin/Field/FieldFormatter. Создайте её и файл вручную:
// web/modules/custom/blog/src/Plugin/Field/FieldFormatter/ReadingTimeFormatter.php
namespace Drupal\blog\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\Attribute\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\StringTranslation\TranslatableMarkup;
#[FieldFormatter(
id: 'blog_reading_time',
label: new TranslatableMarkup('Время чтения'),
field_types: ['text_with_summary', 'text_long'],
)]
class ReadingTimeFormatter extends FormatterBase
{
public function viewElements(FieldItemListInterface $items, $langcode): array
{
$elements = [];
foreach ($items as $delta => $item) {
$minutes = \Drupal::service('blog.reading_time')->minutes((string) $item->value);
$elements[$delta] = [
'#markup' => $this->t('Время чтения: @min мин.', ['@min' => $minutes]),
];
}
return $elements;
}
}В атрибуте field_types перечислены типы полей, для которых форматтер подходит: длинный текст и текст с анонсом. Метод viewElements() получает все значения поля и возвращает массив вывода для каждого. Время считает сервис blog.reading_time из урока о сервисах. Для краткости он получен статически; в настоящем коде его передают через create(), как в блоке.
Использование
Выполните drush cr и откройте «Структура → Типы материалов → Статья → Управление отображением». В строке поля Body в списке «Формат» появится вариант «Время чтения». Выберите его для режима «Анонс» и сохраните — в списке /blog под заголовком статьи вместо текста будет строка вроде «Время чтения: 3 мин.».
Атрибуты и аннотации
До Drupal 10.2 плагины описывали не атрибутами, а аннотациями — особыми комментариями над классом:
// web/modules/custom/blog/src/Plugin/Field/FieldFormatter/ReadingTimeFormatter.php
/**
* @FieldFormatter(
* id = "blog_reading_time",
* label = @Translation("Время чтения"),
* field_types = {"text_with_summary", "text_long"}
* )
*/
class ReadingTimeFormatter extends FormatterBase
{
}Эта запись делает то же, что атрибут выше. В старых примерах и модулях вы встретите именно её. В Drupal 10 и 11 аннотации пока работают, но новый код пишут с атрибутами.
Виды плагинов
| Плагин | Папка в src/Plugin | Для чего |
|---|---|---|
Block | Block | Блоки |
FieldFormatter | Field/FieldFormatter | Вывод значения поля |
FieldWidget | Field/FieldWidget | Поле ввода в форме редактирования |
FieldType | Field/FieldType | Новый тип поля |
Filter | Filter | Фильтр текстового формата |
QueueWorker | QueueWorker | Обработчик очереди задач |
Condition | Condition | Условие показа блоков |
Заготовку любого из них создаёт Drush: drush generate показывает список, например drush generate plugin:field:formatter.
Частая ошибка
Плагин не находится, если путь к файлу не соответствует виду плагина: форматтер, положенный в src/Plugin/FieldFormatter или src/Field/FieldFormatter, Drupal не увидит — нужна именно src/Plugin/Field/FieldFormatter. Вторая причина — совпадающий id: два плагина с одним машинным именем затирают друг друга. Начинайте id с имени модуля.