
在插件系统中,插件不会影响其他插件,添加新方法或在方法运行之前进行一些准备. 通过继承实现扩展并不容易. 相关关系,A插件的更改也将导致相关插件被被动修改. Symfony2的EventDispatcher组件实现了中介器模式以及插件之间的解耦和关联. 例如,在HttpKernel组件中,创建响应后,在将响应发送到客户端时允许系统的其他模块对其进行修改是必要且有用的(例如: 在标头中添加缓存字段). Symfony2内核将分派kernel.response事件,因此侦听该事件的侦听器可以修改Response对象: a)侦听器(PHP对象)告诉特定的调度程序类它想侦听kernel.response事件;在任何时候,Symfony都会告诉调度程序调度kernel.response事件,并将包含Response对象的Event对象传递给事件调度方法EventDispatcher :: dispatch()c)调度程序将通知所有侦听内核的侦听器. 响应事件运行,允许这些侦听器修改Response对象.
使用事件调度事件时,该事件将具有唯一的名称(例如: kernel.response),可以由任意数量的侦听器监视. Event对象同时实例化并传递给所有侦听器. 稍后您将看到,Event对象包含计划事件的数据. 命名约定事件名称可以是任何字符串,但是可以遵循以下命名约定: *仅使用小写字母,数字,点php dispatcher,下划线; *前缀名称使用带点的名称; *结束名称使用当前事件行为的表达动词;当事件名称和事件对象分派器调度事件以通知侦听器时,会将Event对象作为参数传递给侦听器. 基类Event非常简单,只有一种方法可以停止将事件传递给下一个侦听器,没有其他方法. 通常,特定事件的数据保存到Event对象,这便于将数据传递给侦听器. 在kernel.response事件中,传递给侦听器的Event对象是FliterResponseEvent子类的对象,而FliterResponseEvent是Event的子类. FliterResponseEvent包含getReponse和setResponse方法,允许侦听器获取或修改Response对象.
通常: 在创建侦听特定事件的侦听器时,将Event的子类传递给侦听器,并且侦听器可以通过此子类的方法获取和修改信息. 事件分派器(dispatcher)分派器是事件分派系统的核心. 一般而言,调度程序包含侦听器列表. 当需要调度事件时,调度程序将通知该设备中包含的所有侦听器.
1 use Symfony\Component\EventDispatcher\EventDispatcher; 2 3 $dispatcher = new EventDispatcher();关联的侦听器将侦听器添加到调度程序,并侦听特定事件. 调度事件后,调度程序将通知侦听器开始工作. 调度程序使用addListener方法将侦听器(可调用的PHP)添加到事件中.
1 $listener = new AcmeListener(); 2 $dispatcher->addListener('foo.action', array($listener, 'onFooAction'));addListener方法采用三个参数: *侦听器需要侦听的事件的名称; *侦听器(可调用PHP); *可选的优先级整数(值越高,优先级越高,器将被更早触发),默认值为0,如果优先级相同,则首先添加的人将首先被触发;
PHP callable是指能作为参数传入call_user_func()或者传入is_callable()函数执行后返回true的PHP 变量。PHP callable可以是 \Closure实例,一个实现了__invoke方法的对象,或者是表示一个函数的字符串,或者一个表示对象方法或者类方法的数组。 到目前为止,我们看过把一个PHP对象作为器,我们也可以把Closure对象作为器。1 use Symfony\Component\EventDispatcher\Event; 2 3 $dispatcher->addListener('foo.action', function (Event $event) { 4 // will be executed when the foo.action event is dispatched 5 });在上面的示例中,调度了foo.action事件,调度程序调用了AcmeListener :: onFooAction方法,并将Event对象作为唯一参数传递给该方法.
1 use Symfony\Component\EventDispatcher\Event; 2 3 class AcmeListener 4 { 5 // ... 6 7 public function onFooAction(Event $event) 8 { 9 // ... do something 10 } 11 }在实际使用中,您将特定Event子类的对象传递给侦听器,例如FilterResponseEvent:
1 use Symfony\Component\HttpKernel\Event\FilterResponseEvent; 2 3 public function onKernelResponse(FilterResponseEvent $event) 4 { 5 $response = $event->getResponse(); 6 $request = $event->getRequest(); 7 8 // ... 9 }创建和调度事件除了内置事件,我们还可以创建和调度自定义事件. 这是非常有益的. 当我们使用第三方类库时,我们还可以解耦不同的组件,从而使系统更加灵活和健壮. 如果要创建一个event-store.order-静态Event类,将在创建订单时触发该事件.namespace Acme\StoreBundle; final class StoreEvents { /** * The store.order event is thrown each time an order is created * in the system. * * The event listener receives an * Acme\StoreBundle\Event\FilterOrderEvent instance. * * @var string */ const STORE_ORDER = 'store.order'; }此类没有任何方法,也不做任何事情. 它仅定义事件名称,便于管理和组织事件. 侦听此事件的侦听器将传递给FilterOrderEvent对象. 创建一个Event对象,然后,当您调度此新事件时,将创建一个Event对象,并将其传递给调度程序的dispatch()方法,然后调度程序将此Event对象传递给所有侦听该事件的侦听器. 如果不需要将任何信息传递给侦听器,则可以使用系统默认的Symfony \ Component \ EventDispatcher \ Event类. 但是,很多时候,我们需要将特定信息传递给侦听器,然后我们可以创建一个类来继承Symfony \ Component \ EventDispatcher \ Event. 例如,我们需要在所有侦听器中传递订单对象:1 namespace Acme\StoreBundle\Event; 2 3 use Symfony\Component\EventDispatcher\Event; 4 use Acme\StoreBundle\Order; 5 6 class FilterOrderEvent extends Event 7 { 8 protected $order; 9 10 public function __construct(Order $order) 11 { 12 $this->order = $order; 13 } 14 15 public function getOrder() 16 { 17 return $this->order; 18 } 19 }所有侦听器都可以通过FilterOrderEvent的getOrder方法获取订单对象. 调度程序的dispatch()方法通知所有侦听给定事件的侦听器. 有两个参数,一个是要调度的事件的名称,另一个是传递给所有侦听器的Event对象.1 use Acme\StoreBundle\StoreEvents; 2 use Acme\StoreBundle\Order; 3 use Acme\StoreBundle\Event\FilterOrderEvent; 4 5 // the order is somehow created or retrieved 6 $order = new Order(); 7 // ... 8 9 // create the FilterOrderEvent and dispatch it 10 $event = new FilterOrderEvent($order); 11 $dispatcher->dispatch(StoreEvents::STORE_ORDER, $event);FilterOrderEvent对象作为参数传递给调度方法. 现在,任何store.order事件的器都将接收FilterOrderEvent对象,并通过调用getOrder方法获取order对象.
1 // some listener class that's been registered for "store.order" event 2 use Acme\StoreBundle\Event\FilterOrderEvent; 3 4 public function onStoreOrder(FilterOrderEvent $event) 5 { 6 $order = $event->getOrder(); 7 // do something to or with the order 8 }事件订阅者通常通过向调度程序注册侦听器来侦听事件. 侦听器可以侦听一个或多个事件. 侦听事件的另一种方法是使用事件SubScriber. Event SubScriber是一个PHP类,可以告诉调度程序确切的是它预订了哪些事件. 实现EventSubscriberInterface接口,该接口具有静态方法getSubscriberdEvents.namespace Acme\StoreBundle\Event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; class StoreSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { return array( 'kernel.response' => array( array('onKernelResponsePre', 10), array('onKernelResponseMid', 5), array('onKernelResponsePost', 0), ), 'store.order' => array('onStoreOrder', 0), ); } public function onKernelResponsePre(FilterResponseEvent $event) { // ... } public function onKernelResponseMid(FilterResponseEvent $event) { // ... } public function onKernelResponsePost(FilterResponseEvent $event) { // ... } public function onStoreOrder(FilterOrderEvent $event) { // ... } }
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-149111-1.html
飞机伴飞太远