Block API в Drupal 8 была изменена таким образом, что сейчас блоки являются плагинами(plugins) и сущностями(entities) одновременно. Блоки в Drupal 8 совмещают в себе две разных API структуры: Block Plugin API, которое является автономным повторно используемым API, и Block Entity API, которое представляет собой конкретный вариант использования блока и управление его видимости. Это означает, что блоки теперь являются объектами с полями и работают с новой системой плагинов введенной в Drupal 8. То есть теперь Вы можете создавать новые сущности, добавлять в них поля, и отображать их по разному.
Это изменение позволяет разработчикам использовать тот же самый блок в разных регионах, что было невозможно без дополнительных модулей до Drupal 8. По сути, это позволяет Вам создать много экземпляров того же блока. Также, Вы можете делать это когда Вы добавляете блок используя админ интерфейс.
Далее в этой статье мы будем использовать модуль block_example из проекта Examples.
Блоки в Drupal 8
Вместо использования до 4-х разных хуков, чтобы определить блок (как это делалось в Drupal 7), система плагинов позволяет сделать следующее:
- Использовать один файл для каждого блока.
- Если у Вас есть новый блок, то Вы можете скопировать и вставить содержимое файла в новый файл и обновить метаданные и реализацию, и Вы получите новый блок.
- Вместо работы с 4-я разными функциями в четырех разных местах, в одном или двух файлах, Вам нужен только один файл для каждого блока.
- Вся необходимая логика находиться под рукой.
- Метаданные объявляются в том же месте.
- Вам не прийдется переходить в какой-либо файл и объявлять путь к Вашему классу, так-как есть автозагрузка.
- Все содержится и инкапсулируется в одном файле.
Создание простого блока
В проекте Examples Вы найдете модуль block_example, который содержит три примера для разных типов блоков в директории src/Plugin/Block
. Мы попробуем протестировать самый простой пример в котором создается пустой блок. Новый блок называется ExampleEmptyBlock
, и его реализация находится в файле ExampleEmptyBlock.php
.
Классы и аннотации
Все файлы классов должны начинаться с объявления пространства имен(namespace) класса. После создания пространства имен для класса мы расширим класс ядра Drupal BlockBase
для создания класса ExampleEmptyBlock
. С этим мы можем использовать Drupal аннотацию, которая появилась с версии Drupal 8.
Общие PHP аннотации - это закомментированный текст, который позволяет автоматически находить мета-данные и информацию, относящуюся к файлу класса. Пример описанный выше содержит аннотации специально для блока Example: empty block, размещенные во втором комментарии. Используя аннотации, мы сообщаем Drupal-у, что мы хотим зарегистрировать новый тип блока ([user=Block]Block[/user])
, с id example_empty
и административным названием Example: empty block
, что пройдет через систему переводов перед использованием в системе.
Аннотация {inheritdoc} может быть использована в классе, когда вы переопределяете его функцию. Эта аннотация сообщает системе, что необходимо использовать документации класса-родителя.
Обратите внимание, что Drupal не сможет найти блок до тех пор, пока не будет правильной аннотации.
Это расширяет класс BlockBase
в наш ExampleEmptyBlock
, внутри которого мы реализуем метод build()
. Это один из наиболее важных методов, так-как он возвращает массив готовый для рендера и вывода блока.
Очистите все кэши, перейдите на страницу конфигурации /admin/structure/block
и кликните на Place Block для выбора Вашего нового блока.
Добавляем форму конфигурации к блоку
Теперь мы знаем как создать новый тип блока для повторного использования на странице конфигурации блоков, теперь самое время изучить как использовать API для создания формы конфигурации блока. Эта новая настрой позволит Вам использовать пользовательский интерфейс для того, чтобы задать строку, которая будет выводиться в теле блока.
Дополнительные настойки конфигурации обрабатываются следующим образом:
- Используя метод
blockForm()
, в котором Вы можете добавить элементы к получаемому массиву $form. - Используя метод
blockSubmit()
где вы сможете сохранить данные введенные пользователем. - Используя метод
defaultConfiguration()
, который задает значения конфигурации по умолчанию, отображаемые пользователю в момент первого открытия конфигурации.
Создание блока для формы
В этом примере мы будем использовать модуль block_example из проекта Examples. Код конфигурируемого блока размещается в файле block_example/src/Plugin/Block/ExampleConfigurableTextBlock.php
.
Давайте рассмотрим новые возможности и функции:
- Избегайте глобальных функций
В Drupal 8 каждая часть кода содержит в себе все что может нам понадобиться. Это означает, что большинство функций содержатся в классах вместо глобальной видимости, то есть функции l() или t(), которые повсеместно использовались в Drupal 7 больше не рекомендованы. Их функциональность предоставляется классами через систему, называемую внедрение зависимости(dependency injection), которую мы обсудим в отдельной статье. - Расширение базовых классов
Большинство компонентов, таких как блоки и контроллеры, используют шаблон в котором мы расширяем базовый класс. Базовый класс содержит большинство необходимого функционала, как например функцию t(). По этой причине, когда это возможно, полезно расширять базовый класс.В нашем примере мы создаем блок, который расширяет существующий класс BlockBase, что позволяет использовать метод класса $this->t(), делающий то же самое, что и функция t() в Drupal 7. Это дает нам возможность получить доступ к функции t() через вызов метода $this->t()
- Трейты
По сути трейт выполняет ту же роль, что и include, которая часто использовалась в Drupal 7. Он предоставляет дополнительные методы, которые могут быть включены в любой класс. Включая StringTranslationTrait в BlockBase, мы можем использовать любые методы трейта StringTranslationTrait как будто они являются частью BlockBase.
При написании статьи использовались следующие материалы: