php EventManager Module

参考zf2的EventManager,结合实际项目中的需要写了一个简易的EventManager,主要功能有:

  • 订阅者模式;
  • 拦截器;
  • 事件驱动

具体概念就不介绍了,先来看看模块中的几个类或接口。

EventManager是核心模块,主要负责为监听事件,添加拦截器,触发事件,下面看一个例子:

<?php
require 'EventManager.php';
$em = new EventManager();
$em->attach('start', function ($e) {
    printf('the parameter is %s', json_encode($e));
});
$params = array('foo' => 'bar', 'baz' => 'bat');
$em->trigger('start', $params);

输出结果为:the parameter is {"foo":"bar","baz":"bat"}

 

attach方法的原型为:

/**                                                                     
 * attach a listener to an event                                        
 *                                                                      
 * @param $event string|array                                           
 * @param $callback callable                                            
 * @param $priority  int                                                
 */                                                                     
public function attach($event,$callback,$priority=1)                    
{                                                                       
    if(is_array($event))                                                
    {                                                                   
        foreach($event as $name)                                        
        {                                                               
            $this->attach($name,$callback,$priority);                   
        }                                                               
        return;                                                         
    }                                                                   
                                                                        
    if(!$this->events[$event])                                          
        $this->events[$event] = array();                                
    if(!$this->events[$event][self::LISTENER])                          
        $this->events[$event][self::LISTENER] = new SplPriorityQueue(); 
                                                                        
    $listener = new Listener($event,$callback,intval($priority));       
    $this->events[$event][self::LISTENER]->insert($listener,$priority); 
}                                                                       

 三个参数分别为:

  • 需要监听的事件名,可以是多个事件名组成的数组,事件名可以含有通配符;
  • 监听器,任何合法的PHP回调都能作为监听器;
  • 优先级,一个事件有多个监听器时优先级高的监听器先被触发。

InterceptorInterface接口

定义了拦截器需要实现的两个方法:before和after,before方法会先于监听器调用,after方法会在最后被调用,例子如下:

<?php
class Interceptor implements InterceptorInterface
{
    public function before($e = null)
    {
        printf('before ');
    }

    public function after($e = null)
    {
        printf('after ');
    }
}

require 'EventManager.php';
$em = new EventManager();
$em->attach('start', function ($e) {
    printf('start ');
});
$em->attach('sta*', function ($e) {
    printf('sta* ');
}, 3);
$em->intercept('start', new Interceptor());
$em->trigger('start');

 输出结果为:before sta* start after

另外还有Listener类和StaticEventManager,后者是一个全局的EventManager,具体实现可查看代码。

<?php
interface InterceptorInterface
{
    public function before();

    public function after();
}

class Listener
{
    protected $event = null;
    protected $callback = null;
    protected $priority = 1;

    public function __CONSTRUCT($event, $callback, $priority)
    {
        $this->event = $event;
        $this->callback = $callback;
        $this->priority = $priority;
    }

    public function setEvent($event)
    {
        $this->event = $event;
    }

    public function getEvent()
    {
        return $this->event;
    }

    public function setCallBack($callback)
    {
        $this->callback = $callback;
    }

    public function getCallBack()
    {
        return $this->callback;
    }

    public function setPriority($priority)
    {
        $this->priority = $priority;
    }

    public function getPriority()
    {
        return $this->priority;
    }
}

class StaticEventManager
{

    protected static $instance = null;

    protected function __CONSTRUCT()
    {
    }

    static public function ins()
    {
        if (self::$instance === null) {
            self::$instance = new EventManager();
        }
        return self::$instance;
    }
}

class EventManager
{
    /**
     * type
     */
    const LISTENER = 0;
    const INTERCEPTOR = 1;

    /**
     * Subscribed events and their listeners and interceptors
     */
    protected $events = array();

    /**
     * intercept the event with an interceptor
     *
     * @param $event string|array
     * @param $interceptor InterceptorInterface
     */
    public function intercept($event, InterceptorInterface $interceptor)
    {
        if (is_array($event)) {
            foreach ($event as $name) {
                $this->Intercept($name, $interceptor);
            }
            return;
        }

        if (!isset($this->events[$event]))
            $this->events[$event] = array();
        if (!isset($this->events[$event][self::INTERCEPTOR]))
            $this->events[$event][self::INTERCEPTOR] = array();

        $this->events[$event][self::INTERCEPTOR][] = $interceptor;
    }

    /**
     * attach a listener to an event
     *
     * @param $event string|array
     * @param $callback callable
     * @param $priority  int
     */
    public function attach($event, $callback, $priority = 1)
    {
        if (is_array($event)) {
            foreach ($event as $name) {
                $this->attach($name, $callback, $priority);
            }
            return;
        }

        if (!isset($this->events[$event]))
            $this->events[$event] = array();
        if (!isset($this->events[$event][self::LISTENER]))
            $this->events[$event][self::LISTENER] = new SplPriorityQueue();

        $listener = new Listener($event, $callback, intval($priority));
        $this->events[$event][self::LISTENER]->insert($listener, $priority);
    }

    /**
     * trigger listeners of an event
     *
     * @param $event string|array
     * @param $params
     */
    public function trigger($event, $params = null)
    {
        if (is_array($event)) {
            foreach ($event as $name) {
                $this->trigger($name, $callback, $priority);
            }
            return;
        }

        $matchEvents = $this->getMatchEvents($event);
        $interceptors = array();
        $listeners = new SplPriorityQueue();

        foreach ($matchEvents as $e) {
            $interceptors = array_merge($interceptors, $this->getInterceptors($e));
            $this->insertListeners($listeners, $this->getListeners($e));
        }

        foreach ($interceptors as $interceptor) {
            $interceptor->before($params);
        }
        $this->triggerListeners($listeners, $params);
        foreach ($interceptors as $interceptor) {
            $interceptor->after($params);
        }
    }

    /**
     * retrieve all registered events
     *
     * @return array
     */
    public function getEvents()
    {
        return array_keys($this->events);
    }

    /**
     * retrieve all matched events for a given event
     *
     * @return array
     */
    public function getMatchEvents($event)
    {
        $allEvents = $this->getEvents();
        $matchEvents = array();

        foreach ($allEvents as $key) {
            if (preg_match('/' . $key . '/i', $event)) {
                $matchEvents[] = $key;
            }
        }
        return $matchEvents;
    }

    /**
     * retrieve all listeners for a given event
     *
     * @param  $event string
     * @return SplPriorityQueue
     */
    public function getListeners($event)
    {
        $listeners = new SplPriorityQueue();
        if ($this->events[$event][self::LISTENER])
            $listeners = $this->events[$event][self::LISTENER];
        return $listeners;
    }

    /**
     * retrieve all interceptors for a given event
     *
     * @param  $event string
     * @return array
     */
    protected function getInterceptors($event)
    {
        $interceptors = array();
        if (isset($this->events[$event][self::INTERCEPTOR]))
            $interceptors = $this->events[$event][self::INTERCEPTOR];
        return $interceptors;
    }

    /**
     * Trigger listeners
     *
     * @param  $listeners array
     * @param  $params
     */
    protected function triggerListeners($listeners, $params = null)
    {
        foreach ($listeners as $listener) {
            call_user_func($listener->getCallBack(), $params);
        }
    }

    /**
     * Add listeners to the master queue of listeners
     *
     * @param  PriorityQueue $masterListeners
     * @param  PriorityQueue $listeners
     * @return void
     */
    protected function insertListeners($masterListeners, $listeners)
    {
        if (!count($listeners)) {
            return;
        }

        foreach ($listeners as $listener) {
            $priority = $listener->getPriority();
            if (null === $priority) {
                $priority = 1;
            }
            $masterListeners->insert($listener, $priority);
        }
    }
}

欢迎交流,如果您有更好的建议,请不吝赐教。

 

 

 

你可能感兴趣的:(设计模式,算法,Excel,oop)