В этом уроке мы разберем как выводить блоки программно через кастомный модуль в Drupal 8.
Примеры кода можно посмотреть на github:
https://github.com/levmyshkin/drupalbook8
Начнем с добавления файла содержащего PHP класс, именно так создаются блоки в Drupal 8 через кастомный модуль. Процесс создания файла такой же как и класса для страницы, как мы делали здесь:
12.3. Создаем кастомный Drupal 8 модуль. Вывод страницы программно.
Только нам нужно создать файл с plugin'ом:
modules/custom/drupalbook/src/Plugin/Block/FirstBlock.php
Давайте скопируем этот код блока и потом разберем каждый из частей кода modules/custom/drupalbook/src/Plugin/Block/FirstBlock.php:
<?php namespace Drupal\drupalbook\Plugin\Block; use Drupal\Core\Access\AccessResult; use Drupal\Core\Block\BlockBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; /** * Provides a block with a simple text. * * @Block( * id = "drupalbook_first_block_block", * admin_label = @Translation("My first block"), * ) */ class FirstBlock extends BlockBase { /** * {@inheritdoc} */ public function build() { $config = $this->getConfiguration(); if (!empty($config['drupalbook_first_block_settings'])) { $text = $this->t('Hello @name in block!', ['@name' => $config['drupalbook_first_block_settings']]); } else { $text = $this->t('Hello World in block!'); } return [ '#markup' => $text, ]; } /** * {@inheritdoc} */ protected function blockAccess(AccountInterface $account) { return AccessResult::allowedIfHasPermission($account, 'access content'); } /** * {@inheritdoc} */ public function blockForm($form, FormStateInterface $form_state) { $config = $this->getConfiguration(); $form['drupalbook_first_block_settings'] = [ '#type' => 'textfield', '#title' => $this->t('Name'), '#description' => $this->t('Who do you want to say hello to?'), '#default_value' => !empty($config['drupalbook_first_block_settings']) ? $config['drupalbook_first_block_settings'] : '', ]; return $form; } /** * {@inheritdoc} */ public function blockSubmit($form, FormStateInterface $form_state) { $this->configuration['drupalbook_first_block_settings'] = $form_state->getValue('drupalbook_first_block_settings'); } }
Теперь нужно почистить кэш, чтобы наш блок подхватился друпалом и мы смогли бы его вывести.
Чтобы вывести блок, нужно теперь зайти в настройку блоков и добавить наш блок:
Выведем наш блок в регоине Left Sidebar или другой колонке, где вам будет удобно.
Начните набирать название вашего блока и друпал автоматически предложит вам выбрать ваш блок. Если вашего блока нет, то проверьте, что нужный код и лежит в нужном файле, а файл лежит в нужной папке и после этого не забудьте почистить кэш.
Теперь когда наш блок вывелся, давайте разберемся как работает код для добавления блока:
В начале файла у нас идет namespace, для определения где должен быть наш файл плагина блока, чтобы друпал мог автоматически подключить его. Также мы подключаем классы из других файлов, используя use.
namespace Drupal\drupalbook\Plugin\Block; use Drupal\Core\Access\AccessResult; use Drupal\Core\Block\BlockBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface;
Дальше в комментариях идет аннотация. Нам не нужно определять блок где-нибудь в YML-файлах, он будет автоматически подгружен друпалом с помощью аннатации.
/** * Provides a block with a simple text. * * @Block( * id = "drupalbook_first_block_block", * admin_label = @Translation("My first block"), * ) */
Здесь мы указываем @Block, что это будет плагин блока. id, admin_label будет автоматически подхватывается друпалом, поэтому id должен быть уникальным. @Translation помогает перевести потом label блока через админку друпала.
class FirstBlock extends BlockBase {
Мы наследуемся от класса BlockBase, вы можете зажать ctrl и кликнуть на BlockBase в PhpStorm и посмотреть какие методы можно переопределить в нашем блоке, мы используем не все из них. Переопределять другие методы можно по мере необходимости.
Давайте разберем дальше методы класса в порядке от более понятному к менее понятному:
/** * {@inheritdoc} */ protected function blockAccess(AccountInterface $account) { return AccessResult::allowedIfHasPermission($account, 'access content'); }
Мы уже рассматривали доступ к странице в этой статье, в блоках мы можем использовать те же права доступа:
http://drupalbook.ru/drupal/126-rout-s-parametrom
Здесь мы используем тот же класс AccessResult.
/** * {@inheritdoc} */ public function blockForm($form, FormStateInterface $form_state) { $config = $this->getConfiguration(); $form['drupalbook_first_block_settings'] = [ '#type' => 'textfield', '#title' => $this->t('Name'), '#description' => $this->t('Who do you want to say hello to?'), '#default_value' => !empty($config['drupalbook_first_block_settings']) ? $config['drupalbook_first_block_settings'] : '', ]; return $form; }
Мы можем использовать отдельную форму настройки блока для каждого блока, который мы создаем программно. Если вы зайдете в настройки блока:
Здесь вы можете увидеть наше поле Name, которое мы добавили в методе blockForm():
Мы используем Drupal Form API для создания полей для формы:
https://www.drupal.org/docs/8/api/form-api
https://api.drupal.org/api/drupal/elements/8.5.x
Мы еще будем разбирать Form API в дальнейшем подробно и сделаем мультстеп попап форму. Пока что вы можете посмотреть какие еще типы полей вы можете использовать с помощью Form API. Каждое поле добавляется с помощью массива. Попробуйте добавить еще полей в форму блока.
/** * {@inheritdoc} */ public function blockSubmit($form, FormStateInterface $form_state) { $this->configuration['drupalbook_first_block_settings'] = $form_state->getValue('drupalbook_first_block_settings'); }
Здесь мы сохраняем значение полей с формы в конфигурацию друпала. Мы также будем рассматривать конфигурацию подробнее в следующих уроках, пока что вам достаточно понимать, что в друпал есть общее хранилище всех конфигураций и все модули используют это хранилище конфигов. Эти конфиги можно переносить с одного вашего сайта на другой. Например если вы изменили настройки блока на локальной копии сайта, то потом эти конфиги можно будет выгрузить и загрузить на живом сайте и ваши настройки блока применяться на живом сайте.
/** * {@inheritdoc} */ public function build() { $config = $this->getConfiguration(); if (!empty($config['drupalbook_first_block_settings'])) { $text = $this->t('Hello @name in block!', ['@name' => $config['drupalbook_first_block_settings']]); } else { $text = $this->t('Hello World in block!'); } return [ '#markup' => $text, ]; }
И теперь основной метод build(), который выводит контент блока. В этом методе мы проверяем конфигурацию блока и если у нас есть Имя, то мы выводим текст с именем. Обратите внимание на метод $this->t(), он позволяет перевести текст через админку друпала на другие языки. Даже если вы делаете сайт на русском языке, то лучше всего все текст писать на английском, а потом обернуть текст в $this->t() и перевести через админку друпала. Также у нас используется placeholder @name, он нужен для того чтобы переводить только нужный текст, а не значения полей, которые мы вводим в конфигарационных формах. Это позволяет избегать множества строк перевода, например если не использовать placeholder, то для перевода в админке будут доступны все варианты текста, которые пройдут через $this->t():
Hello Josh ...
Hello Mike ...
Hello Ivan ...
и так далее.
На этом все я думаю вам стало понятно как выводить и настраивать кастомные блоки в Drupal 8, дальше мы будем рассматривать более сложные примеры с использованием блоков, страниц, форм.
Примеры кода можно посмотреть на github:
https://github.com/levmyshkin/drupalbook8