ZF2-事件管理器(The EventManager)

来源:互联网 发布:java jdk环境变量设置 编辑:程序博客网 时间:2024/04/29 08:44

概述

EventManger是一个为以下使用情况设计的组件:

  • 实现简单的主题/观察者模式
  • 实现面向切面的设计
  • 实现事件驱动的架构

基本的架构允许你添加和解除指定事件的侦听器,无论是在一个实例基础还是一个共享的集合;触发事件;终止侦听器的执行。

快速入门

通常,你将会在一个类中创建一个EventManager

Source code   
use Zend\EventManager\EventManagerInterface;use Zend\EventManager\EventManager;use Zend\EventManager\EventManagerAwareInterface; class Foo implements EventManagerAwareInterface{    protected $events;     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;    }}

上面的代码允许用户访问EventManager实例,或使用一个新的实例重置它;如果不存在,它将会在被用到的时候惰性实例化。

EventManager仅仅对它是否触发了一些事件感兴趣。基础的触发接受三个参数:事件的名字,它通常是当前的函数/方法名;上下文,它通常是当前的对象的实例;和参数,它通常是提供给当前函数/方法的参数。

Source code   
class Foo{    // ... assume events definition from above     public function bar($baz, $bat = null)    {        $params = compact('baz', 'bat');        $this->getEventManager()->trigger(__FUNCTION__, $this, $params);    }}

按顺序,触发事件仅关心否有一些东西侦听了事件。侦听器添加到EventManager,指定一个指定的事件和要通知的回调。回调接受一个Event对象,它有一个用于获取事件名字,上下文和参数的访问器。让我们添加一个侦听器,并且触发事件。

Source code   
use Zend\Log\Factory as LogFactory; $log = LogFactory($someConfig);$foo = new Foo();$foo->getEventManager()->attach('bar', function ($e) use ($log) {    $event  = $e->getName();    $target = get_class($e->getTarget());    $params = json_encode($e->getParams());     $log->info(sprintf(        '%s called on %s, using params %s',        $event,        $target,        $params    ));}); // Results in log message:$foo->bar('baz', 'bat');// reading: bar called on Foo, using params {"baz" : "baz", "bat" : "bat"}"

注意,attach()的第二个参数是一个任何有效的回调;例子中展示了一个匿名函数来保持例子是自包含的。然而,你同样可以使用一个有效的函数名字,一个函数对象,一个引用静态方法的字符串,或一个带有一个指定静态方法或实例方法的回调数组。再一次,任何PHP回调都是有效的。

有时候你可能想要指定一个侦听器没有一个创建了一个EventManager的类的对象实例。Zend Framework通过一个SharedEventCollection的概念来实现它。简单的说,你可以使用一个众所周知的SharedEventCollection来注入一个独立的EventManager实例,并且EventManager实例将会为附加的侦听器来查询它。添加到SharedEventCollection的侦听器与正常的事件管理器大略相同;调用attach与EventManager完全相同,但是在开始需要一个附加的参数:一个指定的实例。还记得创建一个EventManager的实例,我们是如何传递给他__CLASS__的?在使用一个SharedEventCollection时,那个值,或者任何你提供给构造器的数组中的任何字符串,可能用于识别一个实例。作为一个示例,假设我们有一个SharedEventManager实例我们知道已经被注入到我们的EventManager实例中了(对于实例,通过依赖注入),我们可以更改上面的例子来通过共享集合来添加:

Source code   
use Zend\Log\Factory as LogFactory; // Assume $events is a Zend\EventManager\SharedEventManager instance $log = LogFactory($someConfig);$events->attach('Foo', 'bar', function ($e) use ($log) {    $event  = $e->getName();    $target = get_class($e->getTarget());    $params = json_encode($e->getParams());     $log->info(sprintf(        '%s called on %s, using params %s',        $event,        $target,        $params    ));}); // Later, instantiate Foo:$foo = new Foo();$foo->getEventManager()->setSharedEventCollection($events); // And we can still trigger the above event:$foo->bar('baz', 'bat');// results in log message:// bar called on Foo, using params {"baz" : "baz", "bat" : "bat"}"

注意:StaticEventManager

在2.0.0beta3中,你可以使用StaticEventManager单例作为一个SharedEventCollection。这样,你不需要担心在哪或者如何来访问SharedEventCollection;它通过简单的调用StaticEventManager::getInstance()是全局可用的。

要知道,然而,框架不赞成它的使用,并且在2.0.0beta4中,你将通过配置一个SharedEventManager实例并注入到一个单独的EventManager实例中来代替它。

EventManager同样提供了解除侦听器的能力,一个事件的短路执行不论是从一个侦听器还是通过测试侦听器的返回值,测试并循环通过侦听器返回的值,区分侦听器的优先级,以及更多。很多这些功能会在例子中详细讲解。

通配符侦听器

有时候你可能会想要为一个给定的实例的很多事件或全部事件添加相同的侦听器,或者可能,使用一个共享事件集合,很多上下文,并且很多事件。EventManager组件允许这样做。

一次添加多个事件

Source code   
$events = new EventManager();$events->attach(array('these', 'are', 'event', 'names'), $callback);

注意如果你指定了一个优先级,那个优先级将会被用于所有指定的事件。

通过通配符添加

Source code   
$events = new EventManager();$events->attach('*', $callback);

注意如果你指定了一个优先级,那个优先级将会用于这个侦听器触发的任何事件。

上面的代码指定的是任何时间触发将会导致这个特定侦听器的通知。

通过一个SharedEventManager一次添加多个事件

Source code   
$events = new SharedEventManager();// Attach to many events on the context "foo"$events->attach('foo', array('these', 'are', 'event', 'names'), $callback); // Attach to many events on the contexts "foo" and "bar"$events->attach(array('foo', 'bar'), array('these', 'are', 'event', 'names'), $callback);

注意如果你指定了一个优先级,那个优先级将会被用于所有指定的事件。

通过一个SharedEventManager一次添加所有事件

Source code   
$events = new SharedEventManager();// Attach to all events on the context "foo"$events->attach('foo', '*', $callback); // Attach to all events on the contexts "foo" and "bar"$events->attach(array('foo', 'bar'), '*', $callback);

注意如果你指定了一个优先级,那个优先级将会被用于所有指定的事件。

上面的代码指定了上下文“foo”和“bar”,指定的侦听器将会在任何事件触发时被通知。

配置选项

EventManager选项

标识符

给定的EventManager实例可以回答的字符串或字符串数组,当通过一个SharedEventManager访问时。

event_class

一个替代的Event类的名字用于代表传给侦听器的事件。

shared_collections

当触发事件时的一个SharedEventCollection实例。

0 0
原创粉丝点击