zend里的事件管理器主要是为了实现:

1、观察者模式

2、面向切面设计

3、事件驱动构架

事件管理最基本的功能是将监听器与事件连接或断开。不论时连接还是断开都是通过shared collections; 触发事件和中断监听器的执行。

use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerAwareInterface; class Foo implements EventManagerAwareInterface
{
protected $events;
//将EventManager实例注入到Foo类中
public function setEventManager(EventManagerInterface $events)
{
$events->setIdentifiers([
__CLASS__,
get_called_class(),
]); $this->events=$events;
return $this;
}
//如果EventManager实例不存在,则新建一个实例。
public function getEventManager()
{
if (null === $this->events) {
$this->setEventManager(new EventManager());
}
return $this->events;
}
}

EventManager真正感兴趣的时触发事件,最基本的触发方式时通过trigger()方法。

/*file:vendor\zendframework\zend-eventmanager\EventManager.php
*trigger方法的具体内容
*/ public function trigger($eventName, $target = null, $argv = [])
{
$event = clone $this->eventPrototype;
$event->setName($eventName);
$event->setTarget($target);
$event->setParams($argv); return $this->triggerListeners($event);
}

可以看到trigger()方法实际上将触发事件这一行为委托给了triggerListeners()方法

trigger接受三个参数(事件名,目标,参数)

trigger方法将会创建事件的实例并触发事件。trigger调用了setName等几个截断器。这几个方法可以在Event类里面找到,主要用来封装目标环境和被传递进来的参数。

关于目标,官网上讲的是通常为当前对象实例。实际上就是触发事件的元素。可以理解为事件的标识

参数则是提供给事件的参数,通常是传递给当前函数或方法的参数。

举例:

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

之前讲过,EventManager只对触发事件感兴趣。这里触发事件则只关心谁在监听本事件,也就是监听器是谁?

监听器会连接到EventManager,指定一个命名的事件和一个回调函数用来通知相关消息(啥叫相关消息呢?就是你想通知的消息)。回调函数需要接收Event对象,Event对象的获取器可以获取事件的名字,目标,和参数(之前代码实例中有setName,反之则是getName)

代码实例

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
));
}); //以下bar方法调用时,事件会被触发,监听器便会被执行
$foo->bar('baz', 'bat')
//Result:
//bar called on Foo, using params {"baz": "baz", "bat":"bat"}"

attach()的第二个参数可以是任何有效的可调用的PHP函数,可以是匿名函数,也可以使用函数名、仿函数、指向静态函数的字符串、、、、

  有时候呢,你可能想创建一个新的监听器,但又不想创建新的事件。于是你想使用之前创建的事件,这时候你就要将之前的事件设置为shared(就是可分享的,一个事件可以有多个监听器)。我们可以通过SharedEventManager来达成这一目的。

  Zend\EventManager\SharedEventManagerInterface描述了一个聚合数个监听器的对象。这些监听器通过使用标识连接一个或多个事件。SharedEventManager不会触发这些事件。相反,是由EventManager组合SharedEventManager之后查询ShareEventManager获得标识一致的监听器,然后触发。 

use Zend\EventManager\SharedEventManager;

$sharedEvents = new SharedEventManager();
$sharedEvents->attach('Foo', 'bar', function($e){
$event = $e->getName();
$target =get_class($e->getTarget());
$params = $e->getParams();
printf(
'Handled event "%s" on target "%s", with parameters %s',
$event,
$target,
json_encode($params)
);
});

上面代码的attach函数与之前相比添加了第一个参数:‘Foo',意思本监听器的目标是:Foo,事件是:bar,其他的目标不要来找我啦。

  而我们当初创建事件的时候,使用了setIdentifiers()。这个函数便设置了target,也就是标识。

  之前我们使用了ShareEventManager注册了一个监听器,该监听器是共享的。注意:事件不共享,监听器共享。现在我们需要做的就是告诉事件Foo:你可以使用某个监听器啦。我们使用如下代码:

$foo = new Foo();
$foo->getEventManager()->setSharedManager($sharedEvents);
$foo->bar('bar', 'bat');

代码的最后我们触发了bar事件,随之会触发上面的事件,结果就不累述了。

  如果我们使用SubFoo继承Foo类,SubFoo里的bar()仍然会触发我们的共享事件。原因是们在Foo的setIndentifiers()里同时传入了get_class($this),__CLASS__。如果我们在SubFoo里面调用该方法,这两个参数分别返回SubFoo和Foo(__CLASS__相当于get_class()不带参数)。

  

zendframework 事件管理(一)的更多相关文章

  1. zendframework 事件管理(二)

    首先需要明确的几个问题: Q1.什么是事件? A:事件就是一个有名字的行为.当这个行为发生的时候,称这个事件被触发. Q2.监听器又是什么? A:监听器决定了事件的逻辑表达,由事件触发.监听器和事件往 ...

  2. JavaScript 事件管理

    在设计JavaScript xxsdk的时候考虑到能让调用者参与到工作流程中来,开始用了回调函数.如下: this.foo = function(args,callbackFn) { //do som ...

  3. jquery技巧之让任何组件都支持类似DOM的事件管理

    本文介绍一个jquery的小技巧,能让任意组件对象都能支持类似DOM的事件管理,也就是说除了派发事件,添加或删除事件监听器,还能支持事件冒泡,阻止事件默认行为等等.在jquery的帮助下,使用这个方法 ...

  4. Redis事件管理(二)

    Redis的定时器是自己实现的,不是很复杂.说说具体的实现吧. 定时器的存储维护采用的是普通的单向链表结构,具体节点定义为: /*时间定时器结构体*/ typedef struct aeTimeEve ...

  5. Redis事件管理(一)

    Redis统一的时间管理器,同时管理文件事件和定时器, 这个管理器的定义: #if defined(__APPLE__) #define HAVE_TASKINFO 1 #endif /* Test ...

  6. Redis事件管理(三)

    Redis的事件管理和定时器的管理都是自己来实现的,Redis的事件管理分为两部分,一部分是封装了系统的异步事件API,还有一部分是在这基础上封装了一个通用的事件管理器,根据具体的系统来决定具体使用哪 ...

  7. Backbone事件管理——Backbone.Events模块API结构

    模块Backbone.Events的事件管理是通过Backbone提供的Events API来实现的,该API在1.0版本之前仅仅提供了几个基本的方法,如on.off.trigger.once分别执行 ...

  8. phalcon: plugin 结合Manager事件管理、dispatcher调度控制器 监听sql日志记录或其他拦截出来

    可能用到的类 phalcon\mvc\use\plugin Phalcon\Mvc\Dispatcher as MvcDispatcher Phalcon\Events\Manager as Even ...

  9. phalcon:model 事件与事件管理器

    事件与事件管理器(Events and Events Manager)¶ Models allow you to implement events that will be thrown when p ...

随机推荐

  1. 重构9-Extract Interface(提取接口)

    我们来介绍一个常常被忽视的重构:提取接口.如果你发现多于一个类使用另外一个类的某些方法,引入接口解除这种依赖往往十分有用.该重构实现起来非常简单,并且能够享受到松耦合带来的好处. public cla ...

  2. 安装 ant

    (1)下载ant:http://ant.apache.org/bindownload.cgi (2)解压后放在指定的文件夹中(/usr/lib) (3) sudo chmod 777 /usr/lib ...

  3. linux初学 :linux 常用命令(二)

    压缩和解压命令 gzip/guzip   zip/unzip   tar gzip和gunzip一般可用参数是-r,例: gzip test.txt 压缩文件 gzip -r test 压缩所有tes ...

  4. 查看centos中的用户和用户组

    用户列表文件:/etc/passwd 用户组列表文件:/etc/group 查看系统中有哪些用户:cut -d : -f 1 /etc/passwd查看可以登录系统的用户:cat /etc/passw ...

  5. JavaScript之canvas

    num.push(x,y); 动画草图(举个栗子,我们把数字“2”给画出来): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...

  6. 【转载】#273 - Parameter Modifier Summary

    Here's a summary of the different parameter modifiers and how the behavior changes for each, when us ...

  7. linux 信号列表和基本作用

    我们运行如下命令,可看到Linux支持的信号列表: $ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7 ...

  8. tomcat的OutOfMemoryError(PermGen space)解决方法

    修改TOMCAT_HOME/bin/catalina.bat,在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: set J ...

  9. JS学习第三课

    写表格时最好自己写上<tbody>,因为在JS里面要用,要不然html里没有,但是我们在JS里面用得飞起,也说不过去啊. 获取表格元素时,tBodis[0]一定要加上,本人试过不加,然后就 ...

  10. Facebook抛弃了HTML5,微信却捧火了它

    苹果普及了HTML5技术,Facebook押注HTML5上,却受到不小的打击,导致在后来一段时间里,唱衰HTML5的言论成为媒体的一种幸灾乐祸的态度,人人避而不谈.微信通过公众号的形式,以游戏.营销重 ...