Хабрахабр

[Перевод] PSR-14 — главное событие в PHP

В прошлом году PHP-FIG — Группа концепций совместимости PHP, выпустила несколько новых спецификаций. Последняя из них — PSR-14, посвящена диспетчеризации событий. Как и другие PSR, это локальная спецификация, но имеет большое влияние на многие аспекты стандартизации.

От переводчика: Это перевод первой части целой серии публикаций, в которой Larry (Crell) Garfield, один из членов PHP-FIG, объясняет, что такое PSR-14, на что способен, а на что нет, и как лучше всего использовать его в своих проектах.

Цель

Диспетчеризация событий давно используется во многих языках. Если вы когда-нибудь использовали EventDispatcher в Symfony, Event system в Laravel, хуки в Drupal, Event Manager во фреймворке Zend, пакет League\Event, или что-то подобное, то понимаете о чём речь.

Один фрагмент кода отправляет сообщение типа — «событие», а посредник передает его другим отдельным фрагментам кода — «слушателям». В общем смысле, все эти системы представляют из себя некую форму «наблюдателя-посредника». Конечно же, они все разные и не очень совместимы между собой. Иногда сигнал направлен только в одну сторону, иногда «слушатель» может как-то передавать данные обратно вызывающей стороне.

Многие библиотеки можно расширить через отправку событий в той или иной форме, чтобы другой код мог связаться с ними. Это проблема для автономных библиотек, которые хотят подключаться к различным библиотекам и приложениям. Библиотека, которая запускает Symfony EventDispatcher, затем объединяется с Symfony. Но такой посреднический слой, фактически, проприетарный. Библиотека, которая вызывает связывающую систему от Drupal module_invoke_all(), затем связывается с Drupal. Тогда использование ее где-то еще требует установки EventDispatcher и соединения с библиотеками в программе. И так далее.

Это позволяет библиотекам расширяться через тонкий общий слой, и потом облегчит их перенос в другую среду без дополнительных усилий и затрат, например, в Symfony, Zend Framework, Laravel, TYPO3, eZ Platform или Slim. Цель PSR-14 — избавить библиотеки от этой зависимости. Пока у среды есть совместимость с PSR-14, всё будет работать.

Спецификация

Как уже говорил, спецификация довольно легкая. Это три интерфейса в одном методе и мета-описание, как их использовать. Все просто и удобно. Ниже код этих интерфейсов (без комментариев для экономии места).

namespace Psr\EventDispatcher; interface EventDispatcherInterface
{ public function dispatch(object $event);
} interface ListenerProviderInterface
{ public function getListenersForEvent(object $event) : iterable;
} interface StoppableEventInterface
{ public function isPropagationStopped() : bool;
}

Первые два это ядро спецификации. StoppableEventInterface — это расширение, к которому вернёмся позже.

Само событие, однако, не определено — им может быть любой PHP-объект. Думаю, EventDispatcher большинству из вас знаком — это всего лишь объект с методом, которому вы передаете событие — посредник, о котором уже говорили. Подробнее об этом позже.

Для PSR-14 мы сознательно разделили эти две обязанности на отдельные объекты. Большинство существующих реализаций имеют один объект или набор функций, которые работают как посредник или диспетчер и место для регистрации кода, которое получает событие (слушателей). Диспетчер получает список слушателей от объекта поставщика, который составляет этот список.

Да откуда хочет! Откуда тогда поставщик получает список слушателей? Еще в начале мы решили, что стандартизация «Единого Истинного Пути» регистрации слушателей будет слишком ограничена. Существует миллиард и один способ связать слушателя и событие, все они абсолютно действующие и несовместимые. Однако, стандартизировав процесс подключения слушателя к диспетчеру, можно получить отличную гибкость, не заставляя пользователя делать что-то странное и непонятное.

Им может быть любой способный к восприятию сигнала фрагмент PHP: функция, анонимная функция, метод объекта, всё что угодно. Также в коде не указывается, что представляют из себя слушатель. Поскольку вызываемый объект может делать что угодно, это значит, что допустимо иметь в качестве слушателя, скажем, анонимную функцию, которая выполняет отложенную загрузку сервиса из DI-контейнера и вызывает в сервисе метод, который на самом деле и содержит слушающий код.

Поставщики слушателей предлагают надёжный и гибкий API для интеграторов фрэймворков, а отношения между диспетчером и провайдером объединяют их вместе. Вкратце, диспетчер это простой и лёгкий API для авторов библиотек.

Простой пример

В общем виде, схема объединения всех частей в целое, будет выглядеть примерно так.

class Dispatcher implements EventDispatcherInterface
public function dispatch(object $event) { foreach ($this->provider->getListenersForEvent($event) as $listener) { $listener($event); } return $event; }
} $dispatcher = new Dispatcher($provider); $event = new SomethingHappened();
$dispatcher->dispatch($event);

Этот небольшой фрагмент кода открывает большие возможности, и он очень гибкий. В следующих статьях подробно поговорим о его свойствах, разберем некоторые конструкционные решения и рассмотрим множеств способов использования таких легковесных событий.

Код

PSR-14 уже поддерживается основными фреймворками и приложениями.

  • Matthew Weier O’Phinney уже обязался ввести поддержку PSR-14 в zend-eventmanager 4.0 во фрэймворке Zend.
  • Symfony недавно анонсировали изменения в EventDispatcher для совместимости с PSR-14, что даст полную поддержку в 5.0/5.1.
  • Фрэймворк Yii объявил о намерении интегрировать PSR-14 в версии 3.0.
  • Benni Mack из TYPO3 CMS заявил, что в следующем релизе TYPO3 все существующие концепции типа «ловушка+сигнал/слот» будут поддерживать PSR-14.

Также PSR-14 имеет три полнофункциональные независимые реализации, которые вы уже можете использовать в любом приложении.

  • Tukio от Larry Garfield, автора этой статьи.
  • Phly Event Dispatcher от Matthew Weier O’Phinney.
  • Kart от Benni Mack, который работает как встраиваемый плагин.

Автор благодарит всю рабочую группу PSR: Larry Garfield, Cees-Jan Kiewiet, Benjamin Mack, Elizabeth Smith, Ryan Weaver, Matthew Weier O’Phinney. На протяжении всей работы процесс был в высшей степени продуктивным: все работали вместе, коллективно, как и должно быть. Результат радует, и хотелось бы, чтобы и все дальнейшие усилия в совместной работе над архитектурой были так же продуктивны.

Второй вариант привлекателен по нескольким причинам. Узнать больше подробностей можно или из оригинала следующей части и документации или 17 мая на PHP Russia. Да и в принципе состав Программного комитета и спикеров невероятно силен, вряд ли найдется хоть одна тема из сферы профессионального использования PHP, которую не удастся обсудить на этой конференции. Например, глава Программного комитета Александр (samdark) Макаров в числе тех, кто внедрил PSR-14 в Yii.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»