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源代码
Oct 09 PHP
一个简单实现多条件查询的例子
Oct 09 PHP
服务器web工具 php环境下
Dec 29 PHP
PHP多个版本的分析解释
Jul 21 PHP
php验证是否是md5编码的简单代码
Apr 01 PHP
php采集内容中带有图片地址的远程图片并保存的方法
Jan 03 PHP
php从字符串创建函数的方法
Mar 16 PHP
php实现点击可刷新验证码
Nov 07 PHP
php处理复杂xml数据示例
Jul 11 PHP
php版微信自动获取收货地址api用法示例
Sep 22 PHP
PHP通过引用传递参数用法分析
Dec 01 PHP
php+jQuery ajax实现的实时刷新显示数据功能示例
Sep 12 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
PHP中读写文件实现代码
2011/10/20 PHP
PHP字符串函数系列之nl2br(),在字符串中的每个新行 (\n) 之前插入 HTML 换行符br
2011/11/10 PHP
php删除指定目录的方法
2015/04/03 PHP
php连接oracle数据库的核心步骤
2016/05/26 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
PHP如何获取Cookie并实现模拟登录
2020/07/16 PHP
通用JS事件写法实现代码
2009/01/07 Javascript
Prototype 学习 Prototype对象
2009/07/12 Javascript
jQuery.extend()的实现方式详解及实例
2013/06/29 Javascript
js页面跳转的问题(跳转到父页面、最外层页面、本页面)
2013/08/14 Javascript
jquery 实现密码框的显示与隐藏示例代码
2013/09/18 Javascript
SuperSlide标签切换、焦点图多种组合插件
2015/03/14 Javascript
js闭包用法实例详解
2016/12/13 Javascript
原生javascript上传图片带进度条【实例分享】
2017/04/06 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
原生JavaScript之es6中Class的用法分析
2020/02/23 Javascript
node脚手架搭建服务器实现token验证的方法
2021/01/20 Javascript
tensorflow识别自己手写数字
2018/03/14 Python
python如何派生内置不可变类型并修改实例化行为
2018/03/21 Python
Python 实现某个功能每隔一段时间被执行一次的功能方法
2018/10/14 Python
对python判断是否回文数的实例详解
2019/02/08 Python
PyQt QListWidget修改列表项item的行高方法
2019/06/20 Python
pandas 空数据处理方法详解
2019/11/02 Python
tensorflow没有output结点,存储成pb文件的例子
2020/01/04 Python
使用pytorch和torchtext进行文本分类的实例
2020/01/08 Python
Windows系统下pycharm中的pip换源
2020/02/23 Python
django教程如何自学
2020/07/31 Python
python实现图片转字符画
2021/02/19 Python
美国办公用品购物网站:Quill.com
2016/09/01 全球购物
优衣库澳大利亚官网:UNIQLO澳大利亚
2017/01/18 全球购物
上海雨人软件技术开发有限公司测试题
2015/07/14 面试题
社区党建工作汇报材料
2014/08/14 职场文书
学雷锋标兵事迹材料
2014/08/18 职场文书
个人投资合作协议书
2014/10/12 职场文书
Python实战之实现简易的学生选课系统
2021/05/25 Python
Django实现WebSocket在线聊天室功能(channels库)
2021/09/25 Python