Блог экспериментатора инженера-разработчика: Infanty.
Я пишу how-to статьи на редкие темы или статьи обзоры - для себя и тех кто со мной работает.
Блог существует при поддержке: "Оккупационных сил Марса".

Более понятно данная тема звучит на английском языке: event dispatcher, dependency injection, service and hooks. Доработаем форму из предшествующего урока добавив в неё необходимый функционал, который упрощённо можно описать следующим образом:

  • На сабмите форме создаётся диспетчер.
  • Этот диспетчер начинает следить за определённым событием формы.
  • При его возникновении, он (диспетчер) через класс события посылает оповещение всем наблюдателям следящим за этим событием.

Первым шагом реализации необходимого функционала станет дополнение функции submitForm в файле DemoForm.php (./modules/demo/src/Form/DemoForm.php). Где необходимо заменить строки:

$config->set('demo.email_address', $form_state['values']['email']);
$config->save(); 

на:

$config->set('demo.email_address', $form_state['values']['email']); 

// Создаём объект диспетчера на основе одноимённого сервиса. 
$dispatcher = \Drupal::service('event_dispatcher');

// Создаём класс события.
// Пример: Dependency Injection - зависимости передаются через конструктор.
$e = new DemoEvent($config);

// Связываем в диспетчере событие (FormID.какая-то_функция-событие) и класс события.
$event = $dispatcher->dispatch('demo_form.save', $e);
// Получение данных из класса события (из какой-то функции класса).
$newData = $event->getConfig()->get();

// Возвращение пакета данных от класса события, например: в текущую конфигурацию. 
$config->merge($newData);
// Сохранение конфигурации.
$config->save(); 

Вторым шагом - реализуем, использованный в коде выше, класс события - в файле:  DemoEvent.php, который необходимо создать в директории: ./modules/demo/src.

 <?php

/**
 * @file
 * Contains Drupal\demo\DemoEvent.
 */

namespace Drupal\demo;

use Symfony\Component\EventDispatcher\Event;
use Drupal\Core\Config\Config;

class DemoEvent extends Event {

  protected $config;

  /**
   * Constructor.
   *
   * @param Config $config
   */
  public function __construct(Config $config) {
    $this->config = $config;
  }

  /**
   * Getter for the config object.
   *
   * @return Config
   */
  public function getConfig() {
    return $this->config;
  }

  /**
   * Setter for the config object.
   *
   * @param $config
   */
  public function setConfig($config) {
    $this->config = $config;
  }

} 

И подключим его в начале файла DemoForm.php в секции use:

 use Drupal\demo\DemoEvent; 

Третьим шагом реализации необходимого функционала станет реализация класса наблюдателя в файле: ConfigSubscriber.php, который необходимо создать в директории: ./modules/demo/src/EventSubscriber.

 <?php

/**
 * @file
 * Contains Drupal\demo\EventSubscriber\ConfigSubscriber.
 */

namespace Drupal\demo\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ConfigSubscriber implements EventSubscriberInterface {

  static function getSubscribedEvents() {
    // Связываем событие (FormID.какая-то_функция-событие) в классе события 
    // и определённую функцию наблюдателя, передавая вес этой связи.
    $events['demo_form.save'][] = array('onConfigSave', 0);
    return $events;
  }

  public function onConfigSave($event) {
    // В функции наблюдателя можно например: получить свойства 
    // класса события (через функцию).
    $config = $event->getConfig();
    // И изменить их.
    $name_website = $config->get('my_name') . " / " . $config->get('my_website');
    $config->set('my_name_website', $name_website);
  }
} 

Осталось только зарегистрировать класс наблюдателя как сервис, для этого в папке модуля создаём файл: demo.services.yml.

 services:
  demo.config_subscriber:
    class: Drupal\demo\EventSubscriber\ConfigSubscriber
    tags:
      - { name: event_subscriber } 

Перед тестированием приведённого выше функционала, необходимо сбросить кэш сайта.

Нововведения, это хорошо, но тот же функционал можно реализовать и с помошью "старых", "добрых" хуков немного потеряв в гибкости. Для этого на первом шаге заменяем:

$config->set('demo.email_address', $form_state['values']['email']);
$config->save(); 

на:

$config->set('demo.email_address', $form_state['values']['email']); 
 
// Вызов хука.
$configData = $config->get();
$newData = \Drupal::service('module_handler')->invokeAll('demo_config_save', array($configData));

$config->merge($newData);
$config->save(); 

И реализуем хук в файле нужного модуля (*.module):

/**
 * Implements hook_demo_config_save().
 * Naming function: modulename_hookname().
 */
function demo_demo_config_save($configValues) {
  $configValues['my_name_website'] = $configValues['my_name'] . " / " . $configValues['my_website'];

  return $configValues;
}

Перед тестированием приведённого выше функционала, необходимо сбросить кэш сайта.