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

Laravel中间件

时间:2023-03-29 19:04:36 PHP

Laravel中间件代码展示protectedfunctionsendRequestThroughRouter($request){#$this->app->instance('request',$request);#Facade::clearResolvedInstance('request');#$this->bootstrap();返回(新管道($this->app))->send($request)->through($this->app->shouldSkipMiddleware()?[]:$this->middleware)->then($this->dispatchToRouter());//$this->dispatchToRouter(),后续继续}new\Illuminate\Routing\Pipeline($this->app):publicfunction__construct(Container$container=null){$this->container=$container;}public函数发送($passable){$this->passable=$passable;返回$this;}公共函数通过($pipes){#####################################################################################$this->中间件=[##\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::类,##\Illuminate\Foundation\Http\Middleware\ValidatePostSize::类,##\App\Http\Middleware\TrimStrings::类,##\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::类,##];#######################################################################################$this->pipes=is_array($pipes)?$管道:func_get_args();return$this;}//中间件本质publicfunctionthen(Closure$destination){$pipeline=array_reduce(array_reverse($this->pipes),$this->carry(),$this->prepareDestination($destination));//经过上面的操作,返回一个匿名函数,接受一个参数return$pipeline($this->passable);}//注意this是在子类中父类carry的,不同的是子类添加异常处理protectedfunctioncarry(){//接受匿名函数$stack参数和$pipe参数,返回匿名函数,然后将这个匿名函数作为第一个参数$stack迭代传入返回函数($stack,$pipe){返回函数($passable)使用($stack,$pipe){if($pipeinstanceofClosure){return$pipe($passable,$stack);}elseif(!is_object($pipe)){list($name,$parameters)=$this->parsePipeString($pipe);$pipe=$this->getContainer()->make($name);$parameters=array_merge([$passable,$stack],$parameters);}else{$parameters=[$passable,$stack];}//中间件的作用是提供一种方便的机制来过滤进入应用程序的HTTP请求//$this->方法默认处理,可以通过via方法return$pipe->{$this->设置方法}(...$参数);};};}protectedfunctionparsePipeString($pipe){//没有参数pipe(class)orpipe(class:param1,param2,param3...)withparameters(parametersseparatedby,)list($name,$parameters)=array_pad(explode(':',$pipe,2),2,[]);如果(is_string($parameters)){$parameters=explode(',',$参数);}//$parameters是[]数组或[param1,param2,param3...]return[$name,$parameters];}protectedfunctionprepareDestination(Closure$destination){returnfunction($passable)use($destination){返回$destination($passable);};}前置条件array_reduce接受三个参数,第一个参数接收一个数组,第二个参数为函数名(也可以是匿名函数,函数参数有两个,分别代表$result和$item),第三个参数(可选),它将被视为数组中的第一个值,如果数组为空,则作为最终返回值。它被称为闭包函数(closures),允许临时创建一个没有指定名称的函数,通过Closure类实现。在给闭包函数赋值时,PHP会自动将这个表达式转换为内置类Closure的对象对象进行赋值。当闭包函数使用use来使用外部数据时,会在闭包对象中生成一个静态属性数组进行存储。当闭包函数使用参数时,会在闭包对象中生成一个参数属性数组进行存储。publicfunctionthen(Closure$destination){$pipeline=array_reduce(array_reverse($this->pipes),$this->carry(),$this->prepareDestination($destination));返回$pipeline($this->passable);}生成最终匿名函数的过程:array_reduce第一次执行时,返回如下简化的匿名函数,作为第一个参数继续迭代:object(Closure)#id(1){["static"]=>array(2){["stack"]=>object(Closure)#1(0){//$this->prepareDestination($destination)}["pipe"]=>string(15)"照亮\Foundation\Http\Middleware\ConvertEmptyStringsToNull"}}第二次:object(Closure)#id(1){["static"]=>array(2){["stack"]=>object(Closure)#id(1){["static"]=>array(2){["stack"]=>object(Closure)#1(0){//$this->prepareDestination($destinationation)}["pipe"]=>string(15)"Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"}}["pipe"]=>string(15)"App\Http\Middleware\TrimStrings"}}第第三次:object(Closure)#id(1){["static"]=>array(2){["stack"]=>object(Closure)#id(1){["static"]=>array(2){["stack"]=>object(Closure)#id(1){["static"]=>array(2){["stack"]=>object(Closure)#1(0){//$this->prepareDestination($destination)}["pipe"]=>string(15)"Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"}}["pipe"]=>string(15)"App\Http\Middleware\TrimStrings"}}["pipe"]=>string(15)"Illuminate\Foundation\Http\Middleware\ValidatePostSize"}}等等,最后得到一个匿名函数为follows(accept一个参数,这个匿名函数内部使用了上述递归形式的$pipe和$stack)function($passable){if($pipeinstanceofClosure){return$pipe($passable,$stack);}elseif(!is_object($pipe)){list($name,$parameters)=$this->parsePipeString($pipe);$pipe=$this->getContainer()->make($name);//实例化中间件$parameters=array_merge([$passable,$stack],$parameters);}else{$parameters=[$passable,$stack];}返回$pipe->{$this->method}(...$parameters);//语法糖模式,因为中间件参数是可选的};最后的匿名函数调用过程(从最外层开始,这也是之前为什么要用array_reverse,逐层拨入,整体处理是:如果是$pipe匿名函数,直接调用。如果是字符串,解析成对应的类和参数,生成类,然后组成一个参数数组。最后调用$pipe->handle)最外层($pipe=Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode):(new\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode)->handle($passable,$stack)执行预操作后,调用$stack($passable)继续下一层($pipe=Illuminate\Foundation\Http\Middleware\ValidatePostSize):(new\Illuminate\Foundation\Http\Middleware\ValidatePostSize)->handle($passable,$stack)执行完前置操作后,调用$stack($passable),继续下一层**等,当每层中间件的前置任务全部完成,即递归执行到最内层(路由分发、解析请求、返回响应),然后从最内层逐层返回执行各层中间件的后处理任务。至此,返回本次请求的响应。**最内层的操作代码展示(即路由分发、解析请求、返回响应),后续分析:即执行了$destination($passable)匿名函数,位于下面方法。protectedfunctionprepareDestination(Closure$destination){returnfunction($passable)use($destination){return$destination($passable);}};}$destination:protectedfunctiondispatchToRouter(){returnfunction($request){$this->app->instance('request',$request);返回$this->router->dispatch($request);};}解释:所有的post操作都执行到最内层,递归的逐层执行,只有在返回的时候才会执行。