Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Событийная модель Zend Framework 2, EventManager

Dd3f18c87b851137000c7427d7bd5d32?s=47 fwdays
November 24, 2012

Событийная модель Zend Framework 2, EventManager

— Общие понятия, используемые паттерны, применение на практике.
— Реализация в Zend Framework 2
— Практические примеры использования EventManager
MVC + Event

Dd3f18c87b851137000c7427d7bd5d32?s=128

fwdays

November 24, 2012
Tweet

More Decks by fwdays

Other Decks in Programming

Transcript

  1. Событийная модель ZF2, EventManager Александр Вронский Smile Ukraine Email: alexandr@vronskiy.name

    Site: http://alexandr.vronskiy.name
  2. Событийная модель • Что это такое? • В чем преимущество?

    • Где использовать? • Как реализовать?
  3. Событийная модель • Event (Событие) • Listener (Обработчик событий) •

    Event Manager (Менеджер событий)
  4. Событийная модель • Событие1 – Слушатель1, 2, 3… • Событие2

    – Слушатель11, 22, 33...
  5. EventManager, базовая архитектура Реализует: • Паттерн subject/observer (Наблюдатель) • Аспекто-ориентированный

    дизайн • Событийно управляемую архитектуру
  6. EventManager – простой пример use Zend\EventManager\EventManager; $events = new EventManager();

    $events->attach('do', function ($e) { printf( ‘Вызвано событие "%s", с параметрами "%s"' $e->getName(), json_encode($e->getParams()) ); }); $params = array('foo' => 'bar', 'baz' => 'bat'); $events->trigger('do', null, $params); //Вызвано событие "do", с параметрами {"foo":"bar","baz":"bat"}
  7. EventManager - Attach • Имя события • Слушатель (callback) •

    Приоритет (опционально) $events->attach('do', $callback); // приоритет по умолчанию $events->attach('do', $callback, 100); // высокий $events->attach('do', $callback, -100); // низкий
  8. EventManager - Trigger • Имя события • «Цель» • Аргументы

    public function foo($bar, $baz) { $params = compact('bar', 'baz'); $this->events()->trigger('do', $this, $params); }
  9. EventManager - Listeners • Слушатель – любой валидный PHP callback

    • Cлушатели получают объект-событие в качестве единственного аргумента function ($e) { $event = $e->getName(); $target = $e->getTarget(); $target = (is_object($target)) ? get_class($target) : gettype($target); $params = $e->getParams(); printf(‘Событие "%s", параметры %s, контекст "%s"', $event, json_encode($params), $target ); }
  10. EventManager - Event interface EventInterface { public function setName($name); public

    function setTarget($target); public function setParam($name, $value); public function setParams($params); public function getName(); public function getTarget(); public function getParam($name, $default = null); public function getParams(); public function stopPropagation($flag = true); public function propagationIsStopped(); };
  11. EventManager - Состав • EventManager • SharedEventManager • StaticEventManager •

    GlobalEventManager • ?!trait ProvidesEvents
  12. EventManager - EventManagerInterface extends SharedEventManagerAwareInterface - EventManagerAwareInterface extends EventsCapableInterface

  13. (Shared|Static)EventManager • Позволяет присоединять «сквозных» слушателей • Подписка на событие

    до создания конкретного экземпляра EventManager • Логирование, кеширование, дебаг и т.д.
  14. (Shared|Static)EventManager use Zend\EventManager\StaticEventManager; $events = StaticEventManager::getInstance(); $events->attach('CoreDateModel', 'do', function($e) {

    $event = $e->getName(); $target = get_class($e->getTarget()); $params = $e->getParams(); printf( 'Handled event "%s" on target "%s", with parameters %s', $event, $target, json_encode($params) ); });
  15. (Shared|Static)EventManager контекст • Каждый EventManager екзепляр может слушать 1 и

    больше контекстов • Определяем в конструкторе или с помощью метода setIdentifier()
  16. Listener Aggregates class LogEvents implements ListenerAggregateInterface { protected $handlers =

    array(); protected $log; public function attach(EventManagerInterface $events) { $this->handlers[] = $events->attach('do',array($this,'log')); $this->handlers[] = $events->attach('doSomethingElse', array($this,'log')); } public function detach(EventManagerInterface $events) { } public function log(Event $e) { $event = $e->getName(); $params = $e->getParams(); $log->info(sprintf('%s: %s', $event, json_encode($params))); } }
  17. Listener Aggregates $doLog = new LogEvents($logger); $events->attachAggregate($doLog); //или $doLog->attach($events);

  18. EventManager – возврат результатов • EventManager->trigger возвращает объект ResponseCollection •

    Можно прервать дальнейшую обработку события
  19. EventManager – возврат результатов ResponseCollection - методы SplStack, +: •

    first() • last() • contains($value) // true/false • stopped()
  20. EventManager – возврат результатов ResponseCollection - методы SplStack, +: •

    first() • last() • contains($value) // true/false • stopped()
  21. EventManager – возврат результатов public function someExpensiveCall($foo, $bar) { $params

    = compact(‘foo', 'bar'); $results = $this->events()->triggerUntil( __FUNCTION__, $this, $params, function ($r) { return ($r instanceof SomeResultClass); }); if ($results->stopped()) { return $results->last(); } // ... do some work ... }
  22. EventManager – возврат результатов $listener = function ($e) { $e->stopPropagation(true);

    };
  23. EventManager – возврат результатов $results = $events->trigger(/* ... */); if

    ($results->stopped()) { return $results->last(); }
  24. Практика – без событий class SuperCMS_CoreDateModel { public function save($date)

    // “Y/d/M” public function load($id) } class Modul1_CoreDateModel { public function save($date) //override public function load($id) //override }
  25. Практика – с событиями class CoreDateModel implements EventManagerAwareInterface { protected

    $events; const AFTER_PREFIX = 'after.'; const BEFORE_PREFIX = 'before.'; public function setEventManager(EventManagerInterface $events) { $events->setIdentifiers(array(__CLASS__,get_called_class())); $this->events = $events; return $this; } public function getEventManager() { if (null === $this->events) { $this->setEventManager(new EventManager()); } return $this->events; }
  26. Практика – с событиями class CoreDateModel implements EventManagerAwareInterface { use

    ProvidesEvents; const AFTER_PREFIX = 'after.'; const BEFORE_PREFIX = 'before.';
  27. Практика – с событиями class CoreDateModel implements EventManagerAwareInterface { use

    ProvidesEvents; const AFTER_PREFIX = 'after.'; const BEFORE_PREFIX = 'before.'; public function save($data){ $params = compact('data'); $params = $this->getEventManager()->prepareArgs($params); $result = $this->getEventManager()->trigger( self::BEFORE_PREFIX . __FUNCTION__, $this, $params); /* -- save in DB -- */ echo json_encode($params); $this->getEventManager()->trigger( self::AFTER_PREFIX . __FUNCTION__, $this, $params); }
  28. Практика – с событиями use Zend\EventManager\StaticEventManager; $listenerModuleVasya = function($e) {

    $event = $e->getName(); $target = get_class($e->getTarget()); // "Example" $params = $e->getParams(); printf( 'Handled event "%s" on target "%s", with parameters %s <br/>', $event, $target, json_encode($params) ); $dt = new DateTime(); $dt->createFromFormat('Y/d/M', $params['data']); $params['data'] = $dt->format('Y-m-d'); };
  29. Практика – с событиями $listenerModuleVasya = function($e) { $event =

    $e->getName(); $target = get_class($e->getTarget()); // "Example" $params = $e->getParams(); printf( 'Handled event "%s" on target "%s", with parameters %s <br/>', $event, $target, json_encode($params) ); $params['data'] = $params['data'] . ' 00:00:00'; };
  30. Практика – с событиями //Где-то в бутстрапе $events = StaticEventManager::getInstance();

    $events->attach('*', 'before.save', $listenerModuleVasya); $events->attach('CoreDateModel', 'before.save', $listenerModulePetya); //Где-то в контроллере $model = new CoreDateModel(); $model->getEventManager()->setSharedManager($events); $model->save('2012/24/11'); --------------- output ----------------------
  31. ZF2 компоненты + Events • Zend/Cache • Zend/Db (TableGateway, RowGateway

    • Zend/ModuleManager • Zend/Mvc • Zend/Session • Zend/View
  32. События и MVC

  33. Список ZF2 events • Zend\Module\Manager: loadModules.pre • Для каждого модуля:

    - Zend\Module\Manager: loadModule.resolve - Zend\Module\Manager: loadModule • Zend\Module\Manager: loadModules.post Module Manager
  34. Список ZF2 events • Zend\Mvc\Application: bootstrap • Zend\Mvc\Application: route •

    Zend\Mvc\Application: dispatch … Application
  35. Список ZF2 events • Zend\Mvc\Controller\ActionController: dispatch • Zend\Mvc\Application: render •

    Zend\View\View: renderer • Zend\View\View: response • Zend\Mvc\Application: finish Application
  36. Список ZF2 events • Zend\Mvc\Application: dispatch.error • Zend\Mvc\Application: render •

    Zend\View\View: renderer • Zend\View\View: response • Zend\Mvc\Application: finish Application
  37. Итоги • Используйте EventManager • Используйте для базиса событийной модели

    в ваших приложений • …
  38. Вопросы??? while(true){ $q = $this->getPoolQuestions()->pop(); if ($q === false) die(‘Goodbye!’);

    echo ($this->getPoolAnswers()->search($q))?:$this->saysRtfm(); echo ‘Next!’; }