- PVSM.RU - https://www.pvsm.ru -
В прошлом году PHP-FIG [1] — Группа концепций совместимости PHP, выпустила несколько новых спецификаций. Последняя из них — PSR-14 [2], посвящена диспетчеризации событий. Как и другие PSR, это локальная спецификация, но имеет большое влияние на многие аспекты стандартизации.
От переводчика: Это перевод первой части целой серии публикаций, в которой Larry (Crell) Garfield, один из членов PHP-FIG, объясняет, что такое PSR-14, на что способен, а на что нет, и как лучше всего использовать его в своих проектах.
Диспетчеризация событий давно используется во многих языках. Если вы когда-нибудь использовали EventDispatcher в Symfony [3], Event system в Laravel [4], хуки в Drupal, Event Manager [5] во фреймворке Zend, пакет LeagueEvent [6], или что-то подобное, то понимаете о чём речь.
В общем смысле, все эти системы представляют из себя некую форму «наблюдателя-посредника». Один фрагмент кода отправляет сообщение типа — «событие», а посредник передает его другим отдельным фрагментам кода — «слушателям». Иногда сигнал направлен только в одну сторону, иногда «слушатель» может как-то передавать данные обратно вызывающей стороне. Конечно же, они все разные и не очень совместимы между собой.
Это проблема для автономных библиотек, которые хотят подключаться к различным библиотекам и приложениям. Многие библиотеки можно расширить через отправку событий в той или иной форме, чтобы другой код мог связаться с ними. Но такой посреднический слой, фактически, проприетарный. Библиотека, которая запускает Symfony EventDispatcher, затем объединяется с Symfony. Тогда использование ее где-то еще требует установки EventDispatcher и соединения с библиотеками в программе. Библиотека, которая вызывает связывающую систему от Drupal module_invoke_all()
, затем связывается с Drupal. И так далее.
Цель PSR-14 — избавить библиотеки от этой зависимости. Это позволяет библиотекам расширяться через тонкий общий слой, и потом облегчит их перенос в другую среду без дополнительных усилий и затрат, например, в Symfony, Zend Framework, Laravel, TYPO3, eZ Platform или Slim. Пока у среды есть совместимость с PSR-14, всё будет работать.
Как уже говорил, спецификация довольно легкая. Это три интерфейса в одном методе и мета-описание, как их использовать. Все просто и удобно. Ниже код этих интерфейсов (без комментариев для экономии места).
namespace PsrEventDispatcher;
interface EventDispatcherInterface
{
public function dispatch(object $event);
}
interface ListenerProviderInterface
{
public function getListenersForEvent(object $event) : iterable;
}
interface StoppableEventInterface
{
public function isPropagationStopped() : bool;
}
Первые два это ядро спецификации. StoppableEventInterface
— это расширение, к которому вернёмся позже.
Думаю, EventDispatcher
большинству из вас знаком — это всего лишь объект с методом, которому вы передаете событие — посредник, о котором уже говорили. Само событие, однако, не определено — им может быть любой PHP-объект. Подробнее об этом позже.
Большинство существующих реализаций имеют один объект или набор функций, которые работают как посредник или диспетчер и место для регистрации кода, которое получает событие (слушателей). Для PSR-14 мы сознательно разделили эти две обязанности на отдельные объекты. Диспетчер получает список слушателей от объекта поставщика, который составляет этот список.
Откуда тогда поставщик получает список слушателей? Да откуда хочет! Существует миллиард и один способ связать слушателя и событие, все они абсолютно действующие и несовместимые. Еще в начале мы решили, что стандартизация «Единого Истинного Пути» регистрации слушателей будет слишком ограничена. Однако, стандартизировав процесс подключения слушателя к диспетчеру, можно получить отличную гибкость, не заставляя пользователя делать что-то странное и непонятное.
Также в коде не указывается, что представляют из себя слушатель. Им может быть любой способный к восприятию сигнала фрагмент PHP: функция, анонимная функция, метод объекта, всё что угодно. Поскольку вызываемый объект может делать что угодно, это значит, что допустимо иметь в качестве слушателя, скажем, анонимную функцию, которая выполняет отложенную загрузку сервиса из DI-контейнера и вызывает в сервисе метод, который на самом деле и содержит слушающий код.
Вкратце, диспетчер это простой и лёгкий API для авторов библиотек. Поставщики слушателей предлагают надёжный и гибкий API для интеграторов фрэймворков, а отношения между диспетчером и провайдером объединяют их вместе.
В общем виде, схема объединения всех частей в целое, будет выглядеть примерно так.
class Dispatcher implements EventDispatcherInterface
{
public function __construct(ListenerProviderInterface $provider)
{
$this->provider = $provider;
}
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 уже поддерживается основными фреймворками и приложениями.
Также PSR-14 имеет три полнофункциональные независимые реализации, которые вы уже можете использовать в любом приложении.
Автор благодарит всю рабочую группу PSR: Larry Garfield [12], Cees-Jan Kiewiet [13], Benjamin Mack [14], Elizabeth Smith [15], Ryan Weaver [16], Matthew Weier O’Phinney [17]. На протяжении всей работы процесс был в высшей степени продуктивным: все работали вместе, коллективно, как и должно быть. Результат радует, и хотелось бы, чтобы и все дальнейшие усилия в совместной работе над архитектурой были так же продуктивны.
Узнать больше подробностей можно или из оригинала следующей части [18] и документации [2] или 17 мая на PHP Russia [19]. Второй вариант привлекателен по нескольким причинам. Например, глава Программного комитета Александр (samdark [20]) Макаров в числе тех, кто внедрил PSR-14 в Yii. Да и в принципе состав Программного комитета и спикеров [21] невероятно силен, вряд ли найдется хоть одна тема из сферы профессионального использования PHP, которую не удастся обсудить на этой конференции.
Автор: e_finkel
Источник [22]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/316822
Ссылки в тексте:
[1] PHP-FIG: https://www.php-fig.org/
[2] PSR-14: https://www.php-fig.org/psr/psr-14/
[3] Symfony: https://symfony.com/doc/current/event_dispatcher.html
[4] Laravel: https://laravel.com/docs/5.8/events
[5] Event Manager: https://docs.zendframework.com/zend-eventmanager/
[6] LeagueEvent: https://event.thephpleague.com/
[7] недавно анонсировали: https://symfony.com/blog/new-in-symfony-4-3-simpler-event-dispatching
[8] в версии 3.0: https://github.com/yiisoft/docs/blob/master/003-roadmap.md#psr-14-event-dispatcher
[9] Tukio: https://github.com/crell/tukio
[10] Phly Event Dispatcher: https://github.com/phly/phly-event-dispatcher
[11] Kart: https://github.com/bmack/kart-composer-plugin
[12] Larry Garfield: https://twitter.com/Crell
[13] Cees-Jan Kiewiet: https://twitter.com/WyriHaximus
[14] Benjamin Mack: https://twitter.com/bennimack
[15] Elizabeth Smith: https://twitter.com/auroraeosrose
[16] Ryan Weaver: https://twitter.com/weaverryan
[17] Matthew Weier O’Phinney: https://twitter.com/mwop
[18] части: https://steemit.com/php/@crell/psr-14-all-about-events
[19] PHP Russia: https://phprussia.ru/2019
[20] samdark: https://habr.com/ru/users/samdark/
[21] спикеров: https://phprussia.ru/2019/abstracts
[22] Источник: https://habr.com/ru/post/450812/?utm_source=habrahabr&utm_medium=rss&utm_campaign=450812
Нажмите здесь для печати.