首页  >  文章  >  php教程  >  zendframework 事件管理(一)

zendframework 事件管理(一)

WBOY
WBOY原创
2016-08-04 08:53:141169浏览

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

1、观察者模式

2、面向切面设计

3、事件驱动构架

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

<span style="color: #0000ff;">use</span><span style="color: #000000;"> Zend\EventManager\EventManagerInterface;
</span><span style="color: #0000ff;">use</span><span style="color: #000000;"> Zend\EventManager\EventManager;
</span><span style="color: #0000ff;">use</span><span style="color: #000000;"> Zend\EventManager\EventManagerAwareInterface;

</span><span style="color: #0000ff;">class</span> Foo <span style="color: #0000ff;">implements</span><span style="color: #000000;"> EventManagerAwareInterface
{
    </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$events</span><span style="color: #000000;">;<br>//将EventManager实例注入到Foo类中
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> setEventManager(EventManagerInterface <span style="color: #800080;">$events</span><span style="color: #000000;">)
    {
        </span><span style="color: #800080;">$events</span>-><span style="color: #000000;">setIdentifiers([
            </span><span style="color: #ff00ff;">__CLASS__</span>,<span style="color: #000000;">
            get_called_class()</span>,<span style="color: #000000;">
            ]);
    
        </span><span style="color: #800080;">$this</span>->events=<span style="color: #800080;">$events</span><span style="color: #000000;">;
        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span><span style="color: #000000;">;
    }<br>//如果EventManager实例不存在,则新建一个实例。
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getEventManager()
    {
        </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> === <span style="color: #800080;">$this</span>-><span style="color: #000000;">events) {
                </span><span style="color: #800080;">$this</span>->setEventManager(<span style="color: #0000ff;">new</span><span style="color: #000000;"> EventManager());
        }
        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>-><span style="color: #000000;">events;
    }
}</span>

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

<span style="color: #008000;">/*</span><span style="color: #008000;">file:vendor\zendframework\zend-eventmanager\EventManager.php
*trigger方法的具体内容
</span><span style="color: #008000;">*/</span>

<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> trigger(<span style="color: #800080;">$eventName</span>,  <span style="color: #800080;">$target</span> = <span style="color: #0000ff;">null</span>,  <span style="color: #800080;">$argv</span> =<span style="color: #000000;"> [])
{
    </span><span style="color: #800080;">$event</span> = <span style="color: #0000ff;">clone</span> <span style="color: #800080;">$this</span>-><span style="color: #000000;">eventPrototype;
    </span><span style="color: #800080;">$event</span>->setName(<span style="color: #800080;">$eventName</span><span style="color: #000000;">);
    </span><span style="color: #800080;">$event</span>->setTarget(<span style="color: #800080;">$target</span><span style="color: #000000;">);
    </span><span style="color: #800080;">$event</span>->setParams(<span style="color: #800080;">$argv</span><span style="color: #000000;">);
    
    </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->triggerListeners(<span style="color: #800080;">$event</span><span style="color: #000000;">);
}</span>

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

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

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

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

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

举例:

<span style="color: #0000ff;">class</span><span style="color: #000000;"> Foo
{<br>//....assume events definition from above
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> bar(<span style="color: #800080;">$baz</span>, <span style="color: #800080;">$bat</span> = <span style="color: #0000ff;">null</span><span style="color: #000000;">) 
    {
        </span><span style="color: #800080;">$params</span> = <span style="color: #008080;">compact</span>('baz', 'bat'<span style="color: #000000;">);
        </span><span style="color: #800080;">$this</span>->getEventManager()->trigger(<span style="color: #ff00ff;">__FUNCTION__</span>, <span style="color: #800080;">$this</span>, <span style="color: #800080;">$params</span><span style="color: #000000;">);
    }
}</span>

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

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

代码实例

<span style="color: #0000ff;">use</span> Zend\<span style="color: #008080;">Log</span>\Factory <span style="color: #0000ff;">as</span><span style="color: #000000;"> LogFactory;
</span><span style="color: #800080;">$log</span> = LogFactory(<span style="color: #800080;">$someConfig</span><span style="color: #000000;">);
</span><span style="color: #800080;">$foo</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Foo();
</span><span style="color: #800080;">$foo</span>->getEventManager()->attach('bar', <span style="color: #0000ff;">function</span>(<span style="color: #800080;">$e</span>) <span style="color: #0000ff;">use</span>(<span style="color: #800080;">$log</span><span style="color: #000000;">) {
    </span><span style="color: #800080;">$event</span> = <span style="color: #800080;">$e</span>-><span style="color: #000000;">getName();
    </span><span style="color: #800080;">$target</span> = <span style="color: #008080;">get_class</span>(<span style="color: #800080;">$e</span>-><span style="color: #000000;">getTarget());
    </span><span style="color: #800080;">$params</span> = json_encode(<span style="color: #800080;">$e</span>-><span style="color: #000000;">getParams());

    </span><span style="color: #800080;">$log</span>->info(<span style="color: #008080;">sprintf</span><span style="color: #000000;">(
        </span>'<span style="color: #000000;">%s called on %s, using params %s,
        $event,
        $target,
        $params
    ));
});

//以下bar方法调用时,事件会被触发,监听器便会被执行
$foo->bar(</span>'baz', 'bat'<span style="color: #000000;">)
//Result:
//bar called on Foo, using params {"baz": "baz", "bat":"bat"}"</span>

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

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

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

<span style="color: #0000ff;">use</span><span style="color: #000000;"> Zend\EventManager\SharedEventManager;

</span><span style="color: #800080;">$sharedEvents</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> SharedEventManager();
</span><span style="color: #800080;">$sharedEvents</span>->attach('Foo', 'bar', <span style="color: #0000ff;">function</span>(<span style="color: #800080;">$e</span><span style="color: #000000;">){
    </span><span style="color: #800080;">$event</span> = <span style="color: #800080;">$e</span>-><span style="color: #000000;">getName();
    </span><span style="color: #800080;">$target</span> =<span style="color: #008080;">get_class</span>(<span style="color: #800080;">$e</span>-><span style="color: #000000;">getTarget());
    </span><span style="color: #800080;">$params</span> = <span style="color: #800080;">$e</span>-><span style="color: #000000;">getParams();
    </span><span style="color: #008080;">printf</span><span style="color: #000000;">(
        </span>'Handled event "%s" on target "%s", with parameters %s',
        <span style="color: #800080;">$event</span>,
        <span style="color: #800080;">$target</span>,<span style="color: #000000;">
        json_encode(</span><span style="color: #800080;">$params</span><span style="color: #000000;">)
    );
});</span>

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

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

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

<span style="color: #800080;">$foo</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Foo();
</span><span style="color: #800080;">$foo</span>->getEventManager()->setSharedManager(<span style="color: #800080;">$sharedEvents</span><span style="color: #000000;">);
</span><span style="color: #800080;">$foo</span>->bar('bar', 'bat');

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

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

 

 

  

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn