Symfony - 事件和事件监听器


Symfony 通过其EventDispatcher组件提供基于事件的编程。任何企业应用程序都需要基于事件的编程来创建高度可定制的应用程序。事件是对象之间交互的主要工具之一。如果没有事件,对象就无法有效地交互。

基于事件的编程过程可以概括为 - 一个称为事件源的对象要求中央调度程序对象注册一个事件,例如 user.registered。一个或多个对象(称为侦听器)向中央调度程序对象询问它想要侦听特定事件(例如 user.registered)。在某个时间点,事件源对象要求中央调度程序对象调度事件,例如 user.registered 以及带有必要信息的事件对象。中央调度程序通知所有侦听器对象有关该事件的信息,例如 user.registered 及其 Event* 对象。

在基于事件的编程中,我们有四种类型的对象:事件源、事件侦听器、事件调度程序和事件本身。

让我们编写一个简单的应用程序来理解这个概念。

步骤 1 - 创建一个项目event-dispatcher-example

cd /path/to/dir 
mkdir event-dispatcher-example 
cd event-dispatcher-example 
composer require symfony/event-dispatcher 

步骤 2 - 创建一个类.User

class User { 
   public $name; 
   public $age; 
}  

$user = new User(); 
$user->name = "Jon"; 
$user->age = 25

步骤 3 - 创建一个事件UserRegisteredEvent

use Symfony\Component\EventDispatcher\Event;  
class UserRegisteredEvent extends Event {
   const NAME = 'user.registered';  
   protected $user;  
   
   public function __construct(User $user) { 
      $this-<user = $user; 
   }  
   public function getUser() { 
      return $this-<user; 
   } 
}  
$event = new UserRegisteredEvent($user);

在这里,UserRegisteredEvent可以访问User对象。事件的名称是user.registered

步骤 4 - 创建一个侦听器UserListener

class UserListener { 
   public function onUserRegistrationAction(Event $event) { 
      $user = $event->getUser(); 
         echo $user->name . "\r\n"; 
         echo $user->age . "\r\n"; 
   } 
}  
$listener = new UserListener(); 

步骤 5 - 创建一个事件调度程序对象。

use Symfony\Component\EventDispatcher\EventDispatcher;  
$dispatcher = new EventDispatcher(); 

步骤 6 - 使用调度程序对象及其方法addListener连接侦听器和事件。

$dispatcher 
   ->addListener( 
      UserRegisteredEvent::NAME,  
      array($listener, 'onUserRegistrationAction'));  

我们还可以添加一个匿名函数作为事件监听器,如以下代码所示。

$dispatcher 
   ->addListener( 
      UserRegisteredEvent::NAME,  
      
      function(Event $event) { 
         $user = $event->getUser(); 
         echo $user->name . "\r\n"; 
      }); 

步骤7 - 最后,使用事件调度程序的方法dispatch触发/调度事件。

 $dispatcher->dispatch(UserRegisteredEvent::NAME, $event);

完整的代码清单如下。

main.php

<?php  
   require __DIR__ . '/vendor/autoload.php';  
   use Symfony\Component\EventDispatcher\EventDispatcher; 
   use Symfony\Component\EventDispatcher\Event;  

   class User { 
      public $name; 
      public $age; 
   }  
   class UserRegisteredEvent extends Event { 
      const NAME = 'user.registered';  
      protected $user;  
      
      public function __construct(User $user) { 
         $this->user = $user; 
      }  
      public function getUser() { 
         return $this->user; 
      } 
   }  
   class UserListener { 
      public function onUserRegistrationAction(Event $event) { 
         $user = $event->getUser(); 
         echo $user->name . "\r\n"; 
         echo $user->age . "\r\n"; 
      } 
   } 
   $user = new User(); 
   $user->name = "Jon"; 
   $user->age = 25;  

   $event = new UserRegisteredEvent($user); 
   $listener = new UserListener();  

   $dispatcher = new EventDispatcher();  
   $dispatcher 
      ->addListener( 
         UserRegisteredEvent::NAME, 
         
         function(Event $event) { 
            $user = $event->getUser(); 
            echo $user->name . "\r\n"; 
         });  
   $dispatcher 
      ->addListener( 
         UserRegisteredEvent::NAME, array($listener, 'onUserRegistrationAction'));

   $dispatcher->dispatch(UserRegisteredEvent::NAME, $event); 
?>

结果

Jon 
Jon 
25

Symfony Web 框架有很多事件,可以为这些事件注册监听器并对其进行相应的编程。示例事件之一是 kernel.exception ,对应的事件是GetResponseForExceptionEvent,它保存响应对象(Web 请求的输出)。这用于捕获异常并使用通用错误信息修改响应,而不是向用户显示运行时错误。