基本的架构允许你添加和解除指定事件的侦听器,无论是在一个实例基础还是一个共享的集合;触发事件;终止侦听器的执行。 快速入门 通常,你将会在一个类中创建一个EventManager。 复制代码 代码如下: use ZendEventManagerEventManagerInterface; use ZendEventManagerEventManager; use ZendEventManagerEventManagerAwareInterface;
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仅仅对它是否触发了一些事件感兴趣。基础的触发接受三个参数:事件的名字,它通常是当前的函数/方法名;上下文,它通常是当前的对象的实例;和参数,它通常是提供给当前函数/方法的参数。 复制代码 代码如下: 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对象,它有一个用于获取事件名字,上下文和参数的访问器。让我们添加一个侦听器,并且触发事件。 复制代码 代码如下: use ZendLogFactory 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实例中了(对于实例,通过依赖注入),我们可以更改上面的例子来通过共享集合来添加: 复制代码 代码如下: use ZendLogFactory as LogFactory;
// Assume $events is a ZendEventManagerSharedEventManager 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"}"
通过通配符添加 复制代码 代码如下: $events = new EventManager(); $events->attach("*", $callback);
注意如果你指定了一个优先级,那个优先级将会用于这个侦听器触发的任何事件。 上面的代码指定的是任何时间触发将会导致这个特定侦听器的通知。 通过一个SharedEventManager一次添加多个事件 复制代码 代码如下: $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一次添加所有事件 复制代码 代码如下: $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);