当前位置: 首页 > 后端技术 > PHP

SymfonyEventDispatcher的使用与解读

时间:2023-03-29 13:50:16 PHP

大家好,本文将在本人实际开发工作中通过实例介绍Symfony的EventDispatcher组件的使用与实现原理。该组件在实际开发过程中非常有用。可以让代码的业务逻辑非常清晰,增加代码的复用性,大大降低代码的耦合度。介绍具体介绍可以查看官方文档。以下是文档地址。文档地址形成一个dispatcher对象,其中保存了事件名称和对应的监听事件,具有全局唯一的事件名称。包含一些需要在订阅者中访问的对象。示例1.初始化并添加相应的监听器事件//BI上报函数$dispatcher->addSubscriber(newMediaPlayerSubscriber());//维护播放器信息统一Symfony\Component\EventDispatcher\EventDispatcher2.事件监听类BIReportSubscriberimplementsEventSubscriberInterface{publicstaticfunctiongetSubscribedEvents(){//监听不同的事件,当事件触发时,会调用onResponse方法return[MusicResponseEvent::NAME=>'onResponse',ChildrenResponseEvent::NAME=>'onResponse',FmResponseEvent::NAME=>'onResponse',NewsResponseEvent::NAME=>'onResponse',];}publicfunctiononResponse(AResponseEvent$event){/**BI报告的一些特定业务逻辑*/}classMediaPlayerSubscriberimplementsEventSubscriberInterface{publicstaticfunctiongetSubscribedEvents(){return[MusicResponseEvent::NAME=>'onResponse',FmResponseEvent::NAME=>'onResponse',ChildrenResponseEvent::NAME=>'onResponse',NewsResponseEvent::NAME=>'onResponse',];}publicfunctiononResponse(AResponseEvent$event){/**一些具体的业务逻辑*维护统一的玩家信息*/}实现getSubscribedEvents方法完成事件绑定当事件触发时,dispatcher会调用绑定的方法,将抛出的事件作为参数输入。事件绑定方法onResponse可以有任何名称。在onResponse方法中,通过$event获取要操作的对象。3.事件代码类FmResponseEventextendsEvent{constNAME='fm.response';//事件名称,唯一的事件标识符protected$request;//监听器中要操作的对象protected$response;//在监听器中要操作的对象publicfunction__construct(Request$request,Response$response){$this->request=$request;$this->response=$response;}/***@returnRequest*/publicfunctiongetRequest(){return$this->request;}/***@returnResponse*/publicfunctiongetResponse(){return$this->response;}}在订阅者的业务逻辑中继承Symfony\Component\EventDispatcher\Event,需要用到$request和$response对象,所以这个事件包含了这两个类的对象。4.触发事件$event=newFmResponseEvent($request,$response);$dispatcher->dispatch($event::NAME,$event);dispatcher会按照优先级顺序执行订阅者中事件绑定的方法代码解读1简化EventDispatcher源码类EventDispatcherimplementsEventDispatcherInterface{private$listeners=array();私有$sorted=array();/***触发事件*/publicfunctiondispatch($eventName,Event$event){if($listeners=$this->getListeners($eventName)){$this->doDispatch($listeners,$eventName,$event);}返回$事件;}/***按事件名称搜索监听器*/publicfunctiongetListeners($eventName){if(empty($this->listeners[$eventName])){returnarray();}if(!isset($this->sorted[$eventName])){$this->sortListeners($eventName);}返回$this->sorted[$eventName];}/***更改优先级以对侦听器进行排序*@paramstring$eventName*/privatefunctionsortListeners($eventName){krsort($this->listeners[$eventName]);$this->sorted[$eventName]=数组();foreach($this->listeners[$eventName]as$priority=>$listeners){foreach($listenersas$k=>$listener){if(\is_array($listener)&&isset($listener[0])&&$listener[0]instanceof\Closure){$listener[0]=$listener[0]();$this->listeners[$eventName][$priority][$k]=$listener;}$this->sorted[$eventName][]=$listener;}}}保护函数doDispatch($listeners,$eventName,Event$event){foreach($listenersas$listener){if($event->isPropagationStopped()){break;}\call_user_func($listener,$event,$eventName,$this);}/***添加订阅器*/publicfunctionaddSubscriber(EventSubscriberInterface$subscriber){foreach($subscriber->getSubscribedEvents()as$eventName=>$params){if(is_string($params)){$this->addListener($eventName,array($subscriber,$params));}elseif(is_string($params[0])){$this->addListener($eventName,array($subscriber,$params[0]),isset($params[1])?$params[1]:0);}else{foreach($paramsas$listener){$this->addListener($eventName,array($subscriber,$listener[0]),isset($listener[1])?$listener[1]:0);}}}}publicfunctionaddListener($eventName,$listener,$priority=0){$this->listeners[$eventName][$priority][]=$listener;取消设置($this->sorted[$eventName]);}}