Share
Embed
Transcript
20 slides
-
Шаблон проектирования Observer event generators event dispatcher event handler event
handler event handler -
Для чего вообще нужны события? • 1. Расширение классов без
их непосредственного изменения • 2. Вынесение кода часто-используемых действий. Например, установка значений created_at и updated_at • 3. Создание очередей и сбор данных по ходу исполнения кода -
Event Dispatcher Component { "require": { "symfony/event-dispatcher": "2.1.*" } }
composer install composer.json: -
Event Dispatcher Component <?php require_once __DIR__.'/vendor/autoload.php'; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\Event;
$dispatcher = new EventDispatcher(); $listener = new AcmeListener(); $dispatcher->addListener( 'foo.action', array($listener, 'onFooAction') ); -
class AcmeListener { // ... public function onFooAction(Event $event) {
// ... do something echo $event->getName(); } } $event = new Event(); $dispatcher->dispatch('foo.action', $event); Event Dispatcher Component -
События в Symfony services: app.listener.location: class: App\DefaultBundle\Listener\LocationListener tags: - {
name: kernel.event_listener, event: kernel.controller } - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse } - { name: kernel.event_listener, event: security.interactive_login } $listener = new LocationListener(); $dispatcher->addListener('kernel.controller', array($listener, 'onKernelController')); $dispatcher->addListener('kernel.response', array($listener, 'onKernelResponse')); $dispatcher->addListener('security.interactive_login', array($listener, 'onSecurityInteractiveLogin')); -
Где же можно применить события на практике? {% render "AppBannerBundle:Banner:top"
with {'place': 'MAIN_HORIZONTAL' } %} Система баннеров -
Система баннеров services: app.listener.banner: class: App\BannerBundle\Listener\BannerListener tags: - { name:
kernel.event_listener, event: kernel.controller } arguments: [@doctrine.orm.entity_manager] class BannerListener { private $em; protected $banners; public function __construct($em) { $this->em = $em; } ... } config.yml: BannerListener.php: -
public function onKernelController($event) { if (HttpKernel::MASTER_REQUEST != $event->getRequestType()) { //
don't do anything if it's not the master request return; } $this->banners = $this->em ->getRepository('AppBannerBundle:Banner')->findByPlaces(); } public function getBanner($place) { return isset($this->banners[$place]) ? $this->banners[$place] : null; } $this->get('app.listener.banner')->getBanner($place); Система баннеров -
public function onKernelRequest(GetResponseEvent $event) { if (HttpKernel::MASTER_REQUEST !== $event->getRequestType()) {
// don't do anything if it's not the master request return; } $context = $this->router->getContext(); $request = $event->getRequest(); if ($request->get('_city')) { $context->setParameter('_city', true); } } Установка параметра для всех ссылок -
public function onKernelController(FilterControllerEvent $event) { if (!is_array($controller = $event->getController())) {
return; } $method = new \ReflectionMethod($controller[0], $controller[1]); foreach ($this->reader->getMethodAnnotations($method) as $annotation) { if ($annotation instanceof MinAccess) { if (!$annotation->execute( $this->security, $this->session, $this->routing) ) { throw new MinAccessException(); } } } } Расширение метода с помощью аннотаций -
public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); if ($exception
instanceof MinAccessException) { $event->setResponse( new RedirectResponse($this->routing->generate('address_edit') )); } } Расширение метода с помощью аннотаций -
public function onSecurityInteractiveLogin($event) { $user = $this->securityContext->getToken()->getUser(); $request = $event->getRequest();
if ($city = $entity->getLocation()) { $url = $this->getCityUrl($city); $this->session->set('_security.target_path', $url); } } Перенаправление после входа -
События Doctrine my.listener: class: App\CityBundle\Listener\CityListener tags: - { name: doctrine.event_listener,
event: prePersist, method: prePersist } class CityListener { public function prePersist(LifecycleEventArgs $args) { $entity = $args->getEntity(); $entityManager = $args->getEntityManager(); if ($entity instanceof City) { $now = new \DateTime(); $entity->setCreatedAt($now); } } } -
• Усложнение кода • Усложнение дебага Минусы использования событий event
generators event dispatcher event handler event handler event handler