Drupal 8. Создание модуля: Основы

Частично вольный перевод статьи "Drupal 8 Module Development, Part 1: Getting Started".

В предверии официального релиза Drupal 8, перед разработчиками существующих модулей все явственней вырастает неизбежная проблема - адаптация своих творений к кординально новым принципам разработки под Drupal. Обьектно-ориентированный подход, связанный с внедрениеи в 8-е ядро Drupal компонентов фреймворка Symfony 2, помимо очевидных преимуществ, несет в себе для многих неизбежную головную боль. Перестройка мышления для программиования на обьектно-ориентированных принципах, вместо привычного функционального подхода, дело не самое легкое. Особенно, если концепции MVC и ООП известны лишь в теории.

Тем не менее, если мы планируем остаться с Drupal`ом, не смотря на грядущие перемены, изучать все эти вещи все-равно придется. И начинать это делать стоит уже сейчас.

Данная серия публикаций направлена на знакомство разработчиков с некоторыми концептуальными моментами нового подхода при написании своих модулей для Drupal 8. В первой части мы рассмотрим базовые задачи, встающие при написании нового проекта. На примере простого модуля, позволяющего выводить некую административную страницу с неким содержанием, используя для этого контроллер Symfony.

Начнем ...

1. Структура файлов модуля

При первом взгляде вовнутрь папки с инсталляцией Drupal 8 изменения в файловой структуре. Все гораздо более прямым. Каждая из папок в корневом каталоге, ядро, модули, профили, сайты и темы, дома его соответствующим компонентам. С этим, как говорится, вы начнете путем размещения модуля внутри папки корневого каталога модулей;

Если заглянуть внутрь дирректории с инсталляцией Drupal 8, то первое, что бросается в глаза - измененная, ставшая более логичной, файловая структура. Теперь каждая из папок в корневом каталоге - ядро, модули, профили, сайты и темы - соответствует компонентам, в ней содержащимся. Для модулей, не входящих в ядро, отныне отведена дирректория modules в самом корне.

Соответственно, файлы нашего тестового модуля с именем, конечно же, foobar, будут находится по адресу: modules/foobar.

2. Создание файлов .INFO и .MODULE

Метод использования .info файлов в Drupal претерпел некоторые изменения. Отныне его содержимое записывается в формате Symfony YAML. С расширением .yml в конце.

Для нашего подопытного модуля(который Foobar, если забыли), перво-наперво следует создать два ключевых файла: foobar.module и foobar.info.yml.

Содержание foobar.info.yml будет таким:

name: Foobar
type: module
description: 'This is a demo for creating Drupal 8 modules.'
package: Custom
version: 8.x-1.0
core: 8.x
dependencies:
- node
- block
hidden: false

Как мы видим, изменился синтаксис в описании параметров модуля. Новый параметр hidden сообщает системе, будет или нет отображаться наш модуль в списке модулей на соответствующей административной странице.

А вот дальше начинается основная веселуха…

3. Создание контроллеров для модуля

Сперва немного теории по MVC (привет Википедия):

  • Модель (Model) - предоставляет некую информацию: данные и методы работы с этими данными, реагирует на запросы, изменяя своё состояние. Не содержит информации, как эти знания можно визуализировать.
  • Представление (View) - отвечает за отображение информации (визуализацию). Часто в качестве представления выступает форма (окно) с графическими элементами.
  • Контроллер (Controller) - обеспечивает связь между пользователем и системой: контролирует ввод данных пользователем и использует модель и представление для реализации необходимой реакции.

Для нашего модуля, в качестве примера, мы напишем совсем простенький контроллер. Файл, содержащий его код (FoobarController.php), должен находиться по следующему пути:

ПАПКА_ИНСТАЛЛЯЦИИ_DRUPAL
-- modules
---- foobar
------ lib
-------- Drupal
---------- foobar
------------ Controller
-------------- FoobarController.php

Структура должна быть именно таковой. В противном случае Symfony ваш контроллер попросту не найдет.

Содержание нашего FoobarController.php будет следующим:

namespace Drupal\foobar\Controller;
 
use Drupal\Core\Controller\ControllerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
 
class FoobarController implements ControllerInterface {
 
  public static function create(ContainerInterface $container) {
    return new static($container->get('module_handler'));
  }
 
  /**
   * Функция(метод), которая вернет нам данные при переходе на определенную страницу.
   */

  public function foobarPage() {
    return array(
      '#markup' => t('This is the demo foobar page.'),
    );
  }
 
}

Код, написанный выше, как раз и формирует то, что мы увидим на страничке, создаваемой нашим модулем.

4. Описываем маршрутизацию для контроллера

Для того, чтобы передать в контроллер путь(URL), по переходу на который он будет возвращать нужные данные, создадим еще один файл в корне нашего модуля - foobar.routing.yml (modules/foobar/foobar.routing.yml). Со следующим кодом:

foobar:
  pattern: 'admin/foobar' // В этом месте мы передаем шаблон пути, по которому будет отрабатывать контроллер.
  defaults:
    _content: '\Drupal\foobar\Controller\FoobarController::foobarPage' // Информируем Symfony о пространстве имен, где следует искать наш контроллер и методе(функции), который вернет нам нужные данные.
  requirements:
    _permission: 'access administration pages'

5. Регистрируем пункт меню

Помимо указания путей-маршрутов для контроллера, в Drupal 8 требуется так же отдельно зарегистрировать путь и для системы меню. В этом деле нам помогут ранее созданный файл foobar.module и старый знакомый - hook_menu().

Открываем foobar.module, и помещаем в него код:

/**
 * Implements hook_menu().
 */

function foobar_menu() {
  // Путь, указанный здесь, должен полностью соответствовать тому пути, что мы указывали в foobar.routing.yml.
  $items['admin/foobar'] = array(
    'title' => 'Foobar',
    'description' => 'This is the demo foobar page.',
    // Название маршрута из foobar.routing.yml.
    'route_name' => 'foobar',
  );
  return $items;
}

6. Заключительная стадия

Теперь мы можем включить наш модуль. В меню раздела административных настроек сайта должен появиться новый пункт. На странице, куда ведет его ссылка, нас будет приветствовать текст - 'This is the demo foobar page'. Или белый экран, если прочитали вышеописанное без должного внимания.)

Эпилог

Кстати сказать, все изложенные безобразия с контроллерами и роутингами, можно было бы обойти написанием кода по-старинке. Игнорируя многочисленные преимущества Symfony, и используя, как и раньше, добрые, понятные хуки. Однако... Такой путь хоть и допустим, но имеет логичный финиш - тупик. Drupal изменился, и прежним никогда не станет. И тут без вариантов: или мы идем с ним в одном направлении, тоже меняясь, или посылаем все это к черту, во избежание сожалений о бесцельно прожитом. И выбирать пора уже вчера.)

пс
Продолжения не будет. Оказалось, что переводы этого цикла на русский уже есть. Правда, автор найденного сайта наивно выдает их за свои труды, судя по отсутствию какого-либо упоминания об оригинале.

Dalay

Комментарии

а какую нибудь инфу о ControllerBase и ControllerAware?

Этой недостаточно? Или что скрывалось под "а какую нибудь инфу"?

Сложилось мнение, что к релизу 8-ры вся эта чехарда с компонентами Symfony претерпит серьезные изменения. Пока же это видится кашей из старого с новым. Для себя пока решил прокачаться по Symfony, к Dru 8 вернусь попозжа.

hook_menu с колбэками останется в 8-ке?

С одной стороны - согласно оф. документации пока тут почти все без изменений. С другой - в вышеупомянутом источнике нет ни слова про route_name, а во всех ядреных модулях(из тех, что довелось поковырять) используется именно указание маршрута, заместо старой схемы с коллбэками. Такая вот задница.

Админ, ждем новые переводы. Тот сайт закрылся, так что твои труды не напрасны.

Поддерживаю, статьи очень помагают

Ребята. Что-то здесь не так.
Нет в версии 8.1.8 ControllerInterface, hook_menu, и т.д. Но многие об этом пишут.
Кто-нибудь выложит нормальное пошаговое руководство. Типа как это, но правильное.
Спасибо.