介绍
参考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); }三个参数分别为:
定义了拦截器需要实现的两个方法: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); } } }
欢迎交流,如果您有更好的建议,请不吝赐教。