12.7. Плагины в Drupal 8. Выводим блок.
В этом уроке мы разберем как выводить блоки программно через кастомный модуль в 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:
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 = @block("My first block"),
* )
*/
class FirstBlock extends BlockBase {
/**
* {@block}
*/
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,
];
}
/**
* {@block}
*/
protected function blockAccess(AccountInterface $account) {
return AccessResult::allowedIfHasPermission($account, 'access content');
}
/**
* {@block}
*/
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;
}
/**
* {@block}
*/
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 = @block("My first block"),
* )
*/
Здесь мы указываем @Block, что это будет плагин блока. id, admin_label будет автоматически подхватывается друпалом, поэтому id должен быть уникальным. @Translation помогает перевести потом label блока через админку друпала.
extends BlockBase {
Мы наследуемся от класса BlockBase, вы можете зажать ctrl и кликнуть на BlockBase в PhpStorm и посмотреть какие методы можно переопределить в нашем блоке, мы используем не все из них. Переопределять другие методы можно по мере необходимости.
Давайте разберем дальше методы класса в порядке от более понятному к менее понятному:
/**
* {@block}
*/
protected function blockAccess(AccountInterface $account) {
return AccessResult::allowedIfHasPermission($account, 'access content');
}
Мы уже рассматривали доступ к странице в этой статье, в блоках мы можем использовать те же права доступа:
https://drupalbook.org/ru/drupal/126-rout-s-parametrom
Здесь мы используем тот же класс AccessResult.
/**
* {@block}
*/
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. Каждое поле добавляется с помощью массива. Попробуйте добавить еще полей в форму блока.
/**
* {@block}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['drupalbook_first_block_settings'] = $form_state->getValue('drupalbook_first_block_settings');
}
Здесь мы сохраняем значение полей с формы в конфигурацию друпала. Мы также будем рассматривать конфигурацию подробнее в следующих уроках, пока что вам достаточно понимать, что в друпал есть общее хранилище всех конфигураций и все модули используют это хранилище конфигов. Эти конфиги можно переносить с одного вашего сайта на другой. Например если вы изменили настройки блока на локальной копии сайта, то потом эти конфиги можно будет выгрузить и загрузить на живом сайте и ваши настройки блока применяться на живом сайте.
/**
* {@block}
*/
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