zoukankan      html  css  js  c++  java
  • zendframework 事件管理(一)

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

    1、观察者模式

    2、面向切面设计

    3、事件驱动构架

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

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

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

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

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

    use ZendEventManagerSharedEventManager;
    
    $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()不带参数)。

      

  • 相关阅读:
    数据结构选讲深入理解红黑树(Red Black Tree)
    [CLRS][CH 15.2] 动态规划之矩阵链乘法
    数据结构选讲树的旋转(Rotation)
    数据结构选讲二叉查找树(Binary Search Tree)
    [SICP][CH 2.2] 层次性数据和闭包性质
    [CLRS][CH 15.3] 动态规划基础
    数据结构选讲234树(234 Tree)
    IEnumerable与IEnumerator
    你日常所做的事情,决定你将永远成为什么样的人
    c#中正则表达中特殊字符的转义!
  • 原文地址:https://www.cnblogs.com/san-fu-su/p/5724295.html
Copyright © 2011-2022 走看看