Zend Framework 2.0事件管理器(The EventManager)入门教程


Posted in PHP onAugust 11, 2014

概述

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

实现简单的主题/观察者模式

实现面向切面的设计

实现事件驱动的架构

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

快速入门

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

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

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 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实例中了(对于实例,通过依赖注入),我们可以更改上面的例子来通过共享集合来添加:

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组件允许这样做。

一次添加多个事件

$events = new EventManager();

$events->attach(array('these', 'are', 'event', 'names'), $callback);

通过通配符添加

$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);

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

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

配置选项

EventManager选项

标识符

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

event_class

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

shared_collections

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

可用方法

__construct

__construct(null|string|int Sidentifier)

构造一个新的EventManager实例,使用给定的标识符,如果提供了的话,为了共享集合的目的。

setEventClass

setEventClass(string $class)

提供替换Event类的名字用在创建传递给触发的侦听器的事件时。

setSharedCollections

setSharedCollections(SharedEventCollection $collections=null)

用于触发事件时的SharedEventCollection实例。

getSharedCollections

getSharedCollections()

返回当前添加到的SharedEventCollection实例。如果没有添加集合,返回空,或者一个SharedEventCollection实例。

trigger

trigger(string $event, mixed $target, mixed $argv, callback $callback)

触发指定事件的所有侦听器。推荐为$event使用当前的函数/方法名,在后面加上诸如“.pre”、“.post”等,如果有需要的话。$context应该是当前对象的实例,或者是函数的名字如果不是使用对象触发。$params通常应该是一个关联数组或者ArrayAccess实例;我们推荐使用传递给函数/方法的参数(compact()在这里通常很有用处)。这个方法同样可以接受一个回调并且表现与triggerUntil()相同。

方法返回一个ResponseCollection的实例,它可以用于反省各种各样的侦听器返回的值,测试短路,以及更多。

triggerUntil

triggerUntil(string $event, mixed $context, mixed $argv, callback $callback)

触发指定事件的所有侦听器,就像trigger(),额外的是它将每个侦听器的返回值传递给$callback;如果$callback返回一个布尔true值,侦听器的执行将被终止。你可以使用$result->stopped()来测试它。

attach

attach(string $event, callback $callback, int $priority)

添加$callback到EventManager实例,侦听事件$event。如果提供了一个$priority,侦听器将会使用那个优先级插入到内部的侦听器堆栈;高的值会先执行。(默认的优先级是“1”,并且运行使用负的值。)

方法返回一个Zend\Stdlib\CallbackHandler的实例;这个值可以在稍后传递给detach(),如果需要的话。

attachAggregate

attachAggregate(string|ListenerAggregate $aggregate)

如果一个字符串被传递作为$aggregate,实例化那个类。$aggregate然后被传递给EventManager实例的attache()方法因此他可以注册侦听器。

返回ListenerAggregate实例。

detach

detach(CallbackHandler $listener)

扫描所有的侦听器,并且取消匹配$listener的所有侦听器因此它们将不再会被触发。

返回一个true布尔值如果任何侦听器已经被指定并且取消订阅,否则返回一个false布尔值。

detachAggregate

detachAggregate(ListenerAggregate $aggregate)

循环所有的事件来确定集合代表的侦听器;对于所有的匹配项,侦听器将会被移除。

如果任何侦听器被确定并被取消订阅返回一个true布尔值,否则返回一个false布尔值。

getEvents

getEvent()

返回一个有侦听器附加的所有事件名字的数组。

getListeners

getListeners(string $event)

返回一个添加到$event的所有侦听器的Zend\Stdlib\PriorityQueue实例

clearListeners

clearListeners(string $event)

移除添加到$event的所有侦听器。

prepareArgs

prepareArgs(array $args)

从提供的$args创建一个ArrayObject。如果你想要你的侦听器可以更改参数让稍后的侦听器或触发的方法可以看到这些更改的情况下着将很有用。

PHP 相关文章推荐
PHP中获取变量的变量名的一段代码的bug分析
Jul 07 PHP
PHP header函数分析详解
Aug 06 PHP
PHP类的静态(static)方法和静态(static)变量使用介绍
Feb 19 PHP
preg_match_all使用心得分享
Jan 31 PHP
php过滤敏感词的示例
Mar 31 PHP
PHP调用Linux命令权限不足问题解决方法
Feb 07 PHP
PHP实现的构造sql语句类实例
Feb 03 PHP
PHP文件上传操作实例详解
Sep 27 PHP
PHP的自定义模板引擎
Mar 24 PHP
PHP实现数组转JSon和JSon转数组的方法示例
Jun 14 PHP
php校验公钥是否可用的实例方法
Sep 17 PHP
php操作redis数据库常见方法实例总结
Feb 20 PHP
php向js函数传参的几种方法
Aug 10 #PHP
本地计算机无法启动Apache故障处理
Aug 08 #PHP
浅析PHP编程中10个最常见的错误
Aug 08 #PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
Aug 08 #PHP
PHP连接sql server 2005环境配置及问题解决
Aug 08 #PHP
getJSON跨域SyntaxError问题分析
Aug 07 #PHP
PHP+FastCGI+Nginx配置PHP运行环境
Aug 07 #PHP
You might like
114啦源码(114la)不能生成地方房产和地方报刊问题4级页面0字节的解决方法
2012/01/12 PHP
将二维数组转为一维数组的2种方法
2014/05/26 PHP
php str_getcsv把字符串解析为数组的实现方法
2017/04/05 PHP
PHP递归遍历文件夹去除注释并压缩php源代码的方法示例
2018/05/23 PHP
javascript下有关dom以及xml节点访问兼容问题
2007/11/26 Javascript
javascript removeChild 使用注意事项
2009/04/11 Javascript
JS中的this变量的使用介绍
2013/10/21 Javascript
查找Oracle高消耗语句的方法
2014/03/22 Javascript
document.forms用法示例介绍
2014/06/26 Javascript
Jquery轮播效果实现过程解析
2016/03/30 Javascript
对javascript继承的理解
2016/10/11 Javascript
Javascript的this用法
2017/01/16 Javascript
原生javascript实现图片放大镜效果
2017/01/18 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
浅谈Vue render函数在ElementUi中的应用
2018/09/06 Javascript
layui添加动态菜单与选项卡 AJAX请求的例子
2019/09/25 Javascript
javascript 使用sleep函数的常见方法详解
2020/04/26 Javascript
js实现简单的倒计时
2021/01/28 Javascript
[00:43]FTP典藏礼包 DOTA2三大英雄霸气新套装
2014/03/21 DOTA
利用soaplib搭建webservice详细步骤和实例代码
2013/11/20 Python
python写的ARP攻击代码实例
2014/06/04 Python
Python基于有道实现英汉字典功能
2015/07/25 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
使用Python和百度语音识别生成视频字幕的实现
2020/04/09 Python
django 数据库返回queryset实现封装为字典
2020/05/19 Python
python re的findall和finditer的区别详解
2020/11/15 Python
东南亚旅游平台:The Trip Guru
2018/01/01 全球购物
三陽商会官方网站:Sanyo iStore
2019/05/15 全球购物
瑞士网球商店:Tennis-Point
2020/03/12 全球购物
JD Sports丹麦:英国领先的运动时尚零售商
2020/11/24 全球购物
完美的中文自荐信
2014/05/24 职场文书
2014年单位法制宣传日活动总结
2014/11/01 职场文书
介绍信怎么写
2015/01/30 职场文书
市场营销计划书
2019/04/24 职场文书
2019年鼓励无偿献血倡议书
2019/09/17 职场文书