Ця стаття є другою з трьох частин серії про те, як побудувати модуль Drupal 8.
Як побудувати модуль Drupal 8:
• Побудова модуля Drupal 8: маршрутизація, контролери і меню посилань
• Побудова модуля Drupal 8: блоки і модулі
• Побудова модуля Drupal 8: управління конфігурацією і службовий контейнер
У першій статті цього циклу ми почали з азів. Ми розглянули, які файли необхідні, щоб повідомити Drupal про нашому модулі, як працює процес маршрутизації і як програмно створити посилання меню в якості конфігурації.
У цій статті ми продовжимо роботу з нашим модулем, який ви можете переглянути в цьому сховищі, і розглянемо два інших важливих функціональних елементи: блоки і форми.
Для цього ми створимо власний блок, який повертає деякий настроюваний текст. Після цього, ми створимо просту форму, що використовується для виводу на екран введених користувачем даних.
Блоки Drupal 8
Крутим нововведенням в Drupal 8 стали більш наочні блоки, що практично перетворив їх у плагіни (нова концепція бренду). Тобто тепер вони являють собою функціональні елементи, які можна використовувати в різних місцях.
Ви можете створити в інтерфейсі блок і використовувати його по всьому сайту — ви більше не обмежені у використанні блоку тільки одним місцем застосування.
Давайте продовжимо і створимо простий тип блоку, який виводить на екран за замовчуванням «Привіт, Світ!«. Все, що нам знадобиться — це один файл класів, розташований в папці src/Plugin/Block кореневої директорії нашого модуля.
Давайте назвемо наш новий тип блоку DemoBlock, і, природно, він повинен буде міститися у файлі з іменем DemoBlock.php. В цей файл ми для початку можемо додати наступне:
$this->t(‘Привіт, Світе!’),
);
}
/**
* {@inheritdoc}
*/
public function access(AccountInterface $account) {
return $account->hasPermission(‘access content’);
}
}
Як і для будь-якого іншого файлу класів, ми починаємо з визначення імен нашого класу. Потім ми використовуємо клас BlockBase, так щоб ми могли розширити його, а також клас AccountInterface, так щоб ми могли отримати доступ до поточного активного користувача. Потім випливає те, з чим ви безумовно не зустрічалися в Drupal 7: анотації.
Анотації є інструментом пояснення PHP, вони розташовані в блоці коментарів того ж файлу, в якому визначається клас. Використовуючи анотації, ми повідомляємо Drupal, що ми хочемо зареєструвати новий тип блоку (@Block) з ідентифікатором demo_block і admin_label — Demo block (передаються через систему перекладу).
Далі, ми розширюємо клас BlockBase в наш власний DemoBlock, всередині якого ми реалізуємо два методи (найбільш поширені з них ми будемо розглядати докладно пізніше). Метод build() — найбільш важливий з них, так як він повертає відображається масив, який буде виводити блок. Метод access) контролює права доступу для перегляду цього блоку.
Параметр, який передається до нього, є екземпляром об’єкта класу AccountInterface, в якості якого в цьому випадку буде виступати поточний користувач.
Ще одна цікава річ, яку я хочу відзначити. Ми більше не використовуємо для перекладу глобально функцію t(), а посилаємося на метод t(), реалізований в батьківському класі.
От і все. Тепер ви можете очистити кеш і перейти на сторінку конфігурації Block layout. Здорово, що типи блоків розташовуються праворуч (де ви можете відфільтрувати), і ви можете розмістити один або декілька з цих типів блоків в різних місцях на вашому сайті.
Конфігурація блоку Drupal 8
Тепер, коли ми розглянули, як створити новий тип блоку, використовуваний в інтерфейсі, давайте продовжимо і додамо для нього форму конфігурації.
Ми зробимо так, щоб ви могли змінити блок, вказати в полі ім’я, після чого блок буде говорити «Привіт» не світу, а цього імені.
По-перше, ми повинні визначити форму, що містить текстове поле. Так у нашому класі DemoBlock ми можемо додати новий метод blockForm():
/**
* {@inheritdoc}
*/
public function blockForm($form, &$form_state) {
$form = parent::blockForm($form, $form_state);
$config = $this->getConfiguration();
$form[‘demo_block_settings’] = array(
‘#type’ => ‘textfield’,
‘#title’ => $this->t(‘Who’),
‘#description’ => $this->t(‘Кому Ви хочете сказати «Привіт»?’),
‘#default_value’ => isset($config[‘demo_block_settings’]) ? $config[‘demo_block_settings’] : «,
);
return $form;
}
Ця форма реалізації API дуже схожа на Drupal 7. Однак є і певні нові елементи. По-перше, ми отримуємо масив $form з батьківського класу (так ми створюємо свою форму на базі існуючої, додаючи власне поле).
Це елементи стандарту OOP. Потім ми витягуємо і зберігаємо конфігурацію цього блоку.
Клас BlockBase визначає метод getConfiguration(), який робить це для нас. І в разі, якщо він був вже встановлений, ми встановлюємо для demo_block_settings значення #default_value.
Тепер настав час надати обробник цієї форми, який буде обробляти значення нашого поля і зберігати його в конфігурації блоку:
/**
* {@inheritdoc}
*/
public function blockSubmit($form, &$form_state) {
$this->setConfigurationValue(‘demo_block_settings’, $form_state[‘values’][‘demo_block_settings’]);
}
Цей метод також знаходиться всередині класу DemoBlock, і все, що він робить, це зберігає значення поля demo_block_settings в якості нового пункту блоку конфігурації (з ключем того ж імені для відповідності).
Нарешті, ми повинні налаштувати наш метод build(), так щоб включити в нього ім’я, яким блок повинен говорити «Привіт!«:
/**
* {@inheritdoc}
*/
public function build() {
$config = $this->getConfiguration();
if (isset($config[‘demo_block_settings’]) && !empty($config[‘demo_block_settings’])) {
$name = $config[‘demo_block_settings’];
}
else {
$name = $this->t(‘ніхто’);
}
return array(
‘#markup’ => $this->t(‘Привіт, @name!’, array(‘@name’ => $name)),
);
}
Досі все було досить просто. Ми отримуємо конфігурацію блоку і якщо значення нашого поля встановлено, ми використовуємо його в операторі виведення на екран. Якщо ні, то використовується загальне вираження. Ви можете очистити кеш і перевірити, чи працює блок.
Для цього відредагуйте блок, щоб призначити йому регіон, і додайте ім’я, яким блок повинен сказати «Привіт!»
Слід також мати на увазі, що вам доведеться ще розібратися з перевіркою безпеки даних, які вводить користувач для виводу на екран. Я не включив цей етап, щоб не роздувати статтю.
Форми Drupal 8
Останнє, що ми сьогодні розглянемо, як створити просту форму. З-за обмежених можливостей цієї статті, я не зможу охопити управління її конфігурацією (збережені значення конфігурації, представлені через форми). Я тільки покажу, як визначаються форми, і як наведені значення виводяться на екран.
В Drupal 8 функції визначення форми згруповані всередині класу. Давайте визначимо простий клас DemoForm у файлі src/Form/DemoForm.php:
’email’,
‘#title’ => $this->t(‘Your .com email address.’)
);
$form[‘show’] = array(
‘#type’ => ‘submit’,
‘#value’ => $this->t(‘Submit’),
);
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, array &$form_state) {
if (strpos($form_state[‘values’][’email’], ‘.com’) === FALSE ) {
$this->setFormError(’email’, $form_state, $this->t(‘This is not a .com email address.’));
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
drupal_set_message($this->t(‘Your email address is @email’, array(‘@email’ => $form_state[‘values’][’email’])));
}
}
Крім елементів стандарту ТМР, все інше повинно виглядати для вас дуже знайомим по Drupal 7. Форма API залишилася значною мірою такий же (за винятком додавання деяких нових елементів форми і цього класу інкапсуляції). Так що ж відбувається у наведеному вище коді?
По-перше, ми оголошуємо область імен класу і використовуємо клас ядра FormBase, щоб ми могли розширити його нашим власним класом DemoForm. Після цього ми реалізуємо чотири методу, три з яких повинні бути вам знайомі. Метод getFormId() є новим. Його використання обов’язково. Він застосовується, просто щоб повертати машинне ім’я форми.
Метод buildForm() також обов’язковий, він створює форму. Як? Так само, як і в Drupal 7. Метод validateForm() є необов’язковим, і його призначення має бути вам зрозуміло з Drupal 7. І, нарешті, метод submitForm() виробляє обробку надання даних. Все дуже логічно і організовано.
Так чого ми намагаємося досягти за допомогою цієї форми? У нас є поле електронної пошти (новий елемент форми в Drupal 8), ми хочемо, щоб користувачі заповнювали його. За замовчуванням Drupal перевіряє, чи є вхідне значення в дійсності адресою електронної пошти.
Але наша функція перевірки визначає, чи належить ця адреса електронної пошти сервера з доменом .com, і якщо немає, то форма видає помилку. І в кінці обробник наданих даних просто виводить повідомлення на сторінці.
І останнє, що нам потрібно зробити, щоб використовувати цю форму, це надати для нього маршрут. Тому відредагуйте файл demo.routing.yml і додайте в нього наступне:
demo.form:
path: ‘/demo/form’
defaults:
_form: ‘DrupaldemoFormDemoForm’
_title: ‘Demo Form’
вимога:
_permission: ‘access content’
Цей код повинен виглядати для вас знайомим за попередній статті, в якій ми розглядали маршрутизацію для простої сторінки. Єдина відмінність полягає в тому, що замість _content в блоці defaults, ми використовуємо _form, щоб вказати, що метою є клас форми. І тому значенням є ім’я класу, який ми тільки що створили.
Очистіть кеш і перейдіть за адресою demo/form, щоб перевірити форму.
Якщо ви знайомі з drupal_get_form(), і ставите питанням, як вам завантажити форму способом, до якого ви звикли по Drupal 7, відповідь полягає у глобальному класі Drupal.
Таким чином, щоб отримати форму, ви можете використовувати його метод formBuilder() і зробити щось на зразок цього:
$form = Drupal::formBuilder()->getForm(‘DrupaldemoFormDemoForm’);
Після цього ви можете повернути $form, яка буде представляти собою відображається масив форми.
Висновок
У цій статті ми продовжили розгляд створення модуля Drupal 8. Ми вивчили два нових функціональних елементи: блоки і форми. Ми дізналися, як створити свій власний тип блоку, який ви можете використовувати для створення блоків в інтерфейсі.
Ми також дізналися, як додати для нього власну конфігурацію і як зберігати значення для подальшого використання. Що стосується форм, я показав вам просту реалізацію класу FormBase, який ми використовували, щоб вивести на екран значення, надані користувачем.
У наступній статті ми побіжно розглянемо форми конфігурації. Ми будемо зберігати значення, надані користувачем, за допомогою конфігурації системи Drupal 8. Крім того, ми розглянемо службовий контейнер і введення залежностей, і як вони працюють в Drupal 8. Побачимося.
Переклад статті «Build a Drupal 8 Module: Blocks and Forms» був підготовлений дружною командою проекту Сайтостроение від А до Я.