php EventManager Module

介绍

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

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

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

EventManager 类

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

$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方法会在最后被调用,例子如下:

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

$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,具体实现可查看代码。

<?
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,$aopObj);
            }
            return;
        }

        if(!$this->events[$event])
            $this->events[$event] = array();
        if(!$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(!$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);
    }

    /**
     * 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($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);                    
        }
    }
}


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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值