一直在使用Laravel框架,非常喜欢laravel框架的中间件。在请求结果之前,如果我们想对路由或请求进行额外的处理,我们可以简单地添加一个Midleware中间件,非常简单方便,不是吗?这几天看到了它的中间件的实现,把自己的心得写下来分享给大家。理解管道模式Laravel的中间件使用管道模式。我们先来了解一下什么是流水线模式:所谓流水线(Pipeline)设计模式就是将数据传输到一个任务序列中。pipeline起到了pipeline的作用,数据在这里pipeline进行处理,传递给下一步。顾名思义,就是加装了很多阀门的长输水管道。所以管道模型大致需要三个角色:管道、阀门和负载(流水)。如下图所示:流水线模式UML模型图在开始代码之前,我们首先要了解流水线模式的模型图。简单实现根据上面的模型图,我们来实现我们理解的pipeline模式的代码:/***PipelineBuilder接口就是pipeline*@methodpipe存储在多个valve中*@methodprocess是output*/interfacePipelineBuilderInterface{公共函数__construct($payload);公共功能管道(StageBuilderInterface$stage);publicfunctionprocess();}//具体管道类PipelineimplementsPipelineBuilderInterface{protected$payload;受保护的$pipes=[];公共函数__construct($payload){$this->payload=$payload;}publicfunctionpipe(StageBuilderInterface$stage){$this->pipes[]=$stage;返回$这个;}publicfunctionprocess(){foreach($this->pipesas$pipe){call_user_func([$pipe,'handle'],$this->payload);}}}//阀门接口interfaceStageBuilderInterface{publicfunctionhandle($payload);}//具体阀门类StageOneBuilder实现StageBuilderInterface{publicfunctionhandle($payload){echo$payload.'真的一个';}}//具体的阀类classStageTwoBuilderimplementsStageBuilderInterface{publicfunctionhandle($payload){echo'帅哥';}}//输出:我好帅$pipeline=newPipeline('I');$pipeline->pipe(newStageOneBuilder)->pipe(newStageTwoBuilder)->process();底层源码我们看一下它的底层源码:return(newPipeline($this->container))->send($request)->through($middleware)->then(function($request)使用($route){return$this->prepareResponse($request,$route->run());});上面的代码是处理请求的部分代码,send()获取待处理的数据,through()获取中间件,then()传递闭包函数基本上,使用laravel管道你可以一个实例对象(object)在多个类之间传递,就像水沿着管道依次流动一样。最后,一层层传递,就得到了从头到尾一系列操作的“最终”结果。模拟laravelpipelineinterfacePipelineInterface{publicfunctionsend($traveler);公共功能通过($stops);公共功能通过($方法);publicfunctionprocess();}interfaceStageInterface{publicfunctionhandle($payload);}classStageOneimplementsStageInterface{publicfunctionhandle($payload){echo$payload.'真的是一个';}}classStageTwo实现StageInterface{publicfunctionhandle($payload){echo'awesomeman';}}类Pipe实现PipelineInterface{protected$container;受保护的$passable;受保护的$pipes=[];受保护的$via='handle';公共函数__construct($container){$this->container=$container;}publicfunctionsend($passable){$this->passable=$passable;返回$这个;}publicfunctionthrough($pipes){$this->pipes=is_array($pipes)?$管道:func_get_args();返回$t他的;}publicfunctionvia($method){$this->via=$method;返回$这个;}publicfunctionprocess(){foreach($this->pipesas$pipe){//返回处理后的结果$this->passable=call_user_func([$pipe,$this->via],$this->passable);}}}$container='a';$payload='wa';$pipe=newPipe($container);//输出:我真是个牛逼的人$pipe->send($payload)->through([(newStageOne),(newStageTwo)])->process();实现laravel中间件真正执行的部分,在示例中只使用了一部分管道方式,比如then()方法和array_reduce、array_reverse函数来处理请求。这部分有空再研究。
