Symfony EventDispatcher

Первым делом - EventDispatcher это реализация паттерна Диспетчер (можете представить себе телефонного диспетчера или диспетчера в аэропорту).

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

Давайте посмотрим, каким классом реализуется диспетчер событий:

$ app/console container:debug | grep dispatcher

debug.event_dispatcher      Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher
event_dispatcher            alias for "debug.event_dispatcher"

Ага, значит диспетчер событий это реализация TraceableEventDispatcher.

Мы знаем, что для оптимизации, Symfony не работает с классами напрямую, и поэтому кэширует многие классы в кэш-директории. Диспетчер событий тоже кэшируется, в файле app/cache/dev/appDevDebugProjectContainer.php, в методе \appDevDebugProjectContainer::getDebug_EventDispatcherService:

$this->services['debug.event_dispatcher'] = new \Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher(
    new \Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher($this),// диспетчер событий
    $this->get('debug.stopwatch'),//
    $this->get('monolog.logger.event', ContainerInterface::NULL_ON_INVALID_REFERENCE)// логгер
);

Как видите TraceableEventDispatcher по сути не является диспетчером событий, а является оберткой над диспетчером ContainerAwareEventDispatcher. Зачем так сделано? Официальный ответ - чтобы узнать какие слушатели были вызваны при наступлении событий (так сказать, для дебага).

ContainerAwareEventDispatcher является потомком класса EventDispatcher.

Вводная часть

Компонент EventDispatcher пытается нас запутать используя термины Listener и Subscriber, но по факту это является одной сущностью - слушателем.

И прежде чем продолжить, хочу определить понятие:

ID сервиса - то имя, которое Вы объявляете в app/config/config.yml в секции services.

В ContainerAwareEventDispatcher есть 2 способа добавления слушателей:

1. Способ

addListenerService($eventName, $callback, $priority = 0) где:

$eventName - имя события, на которое подписываем
$callback - кого подписать - массив вида: [
    0 => ID сервиса,
    1 => метод, который должен быть вызван
]
$priority - приоритет вызова.

Пример использования:

$eventDispatcher = new Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher($container);
$eventDispatcher->addListenerService(
    'kernel.request',
    array(0 => 'assetic.request_listener', 1 => 'onKernelRequest'),
    0
);

таким образом, при срабатывании события kernel.request произойдет вызов:

$listener = new \Symfony\Bundle\AsseticBundle\EventListener\RequestListener();
$listener->onKernelRequest($event);

2. Способ

addSubscriberService($serviceId, $class) где:

$serviceId - кого подписать (ID сервиса)
$class - класс, в котором eventDispatcher возьмет настройки подписки. У данного класса должен существует статичный метод getSubscribedEvents(), данный метод должен отдать массив вида:
[
    $eventName - имя события, на которое подписываем выше указанный сервис => [
        0 => имя метода, который должен быть вызван для срабатывании события $eventName
        1 => приоритет вызова
    ],
    $eventName2 => ...
]

Пример использования:

$eventDispatcher = new Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher($container);
$eventDispatcher->addSubscriberService(
    'debug.debug_handlers_listener',
    'Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener'
);

таким образом Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::getSubscribedEvents() знает на какие события нужно подписать сервис debug.debug_handlers_listener.

Запутано - да, но что поделать, как мы видим Symfony-программисты не ищут легких путей

А еще в TraceableEventDispatcher реализованы методы

  • preProcess - оборачивает каждого слушателя в обертку \Symfony\Component\EventDispatcher\Debug\WrappedListener
  • postProcess - удаляет каждому слушателю обертку \Symfony\Component\EventDispatcher\Debug\WrappedListener

Зачем это происходит, я пока не разобрался, может быть отпишусь позже.

Всем удачки.

Оцени публикацию:
  • 0,0
Оценили человек: 0

Похожие статьи:

Справочники и учебники:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2017 YaPro.Ru

Главная » Веб-мастеру » PHP »