Laravel中间件实现原理详解
本文阐述了Laravel中间件的实现原理。分享给大家参考,如下:
#1什么是中间件?
对于Web应用程序,在实际处理请求之前,我们可能会对请求做出各种判断,然后才能将其传递到更深的层次。而如果我们用if else,一旦需要判断的条件越来越多,就会让代码更难维护,系统之间的耦合性也会增加,中间件就可以解决这个问题。我们可以将这些判断分离出来,做成中间件,可以轻松过滤请求。
Laravel中排名第二的中间件
在Laravel中,中间件的实现依赖于类Illuminate\Pipeline\Pipeline。让我们首先看看触发中间件的代码。这很简单,即在处理之后,请求可以传递给闭包。
公共函数句柄($request,Closure $ next){//为$request做某事返回$ next($ request);}#3中间件的内部实现
如上所述,中间件是通过管道实现的,它的调用在照明\路由\路由器中
return(new Pipeline($ this-container))-send($ request)-through($ middleware)-then(function($ request)use($ route){ return $ this-prepare response($ request,$ route-run($ request));});可以看到中间件执行过程调用了三种方法。让我们看看这三个方法的代码:
发送方法
公共函数send($ passable){ $ this-passable=$ passable;返回$ this}事实上,send方法除了设置一个需要在中间件中处理的对象之外什么都没做,这里是一个HTTP请求实例。
通过方法
公共函数通过($ pipes){ $ this-pipes=is _ array($ pipes)?$ pipes : func _ get _ args();返回$ this}这个}through方法也很简单,就是设置需要什么中间件处理。
然后方法
真正难以理解的是,当时的方法代码非常简单,但却不容易理解。
然后公共函数(闭包$ destination){//然后方法接受一个闭包作为参数,然后它被getInitialSlice包装,getInitialSlice实际上返回一个闭包。如果你不知道什么是闭包,先看看PHP文档$ first slice=$ this-getInitialSlice($ destination)。//逆向中间件数组,主要利用栈的特性。我们来谈谈$ pipes=array _ reverse($ this-pipes)。//先不要读这个call_user_func,它实际上实现了一个由array_reduce返回的闭包return call _ user _ func接下来用array_reduce来处理带有回调函数的数组,所以建议先读一下PHP文档中array_reduce的执行原理。实际上,array _ reduce除了包装闭包并将其交给call_user_func来执行array _ reduce ($ pipes,$ this-get slice(),$ first slice),$ this-passable);}那就没有事后的想法了,那么所有的中间件都完成了,不是很优雅吗?
由于aray_reduce的第二个参数需要一个函数,这里我们将重点介绍getSlice()方法的源代码
protected function get slice(){ return function($ stack,$ pipe){//这里$ stack return function($ passable)use($ stack,$ pipe){ if($ pipe instance of Closure){ return call _ user _ func($ pipe,$ passable,$ stack);} else { list($name,$ parameters)=$ this-ParsePipeString($ pipe);return call _ user _ func _ array([$ this-container-make($ name),$this-method],array_merge([$passable,$stack],$ parameters));} };};}看到可能会头晕,闭包又回到了闭包。为了简化,getSlice()返回一个函数a,而函数a又返回一个函数B.为什么要返回两个函数?因为我们在传递过程中使用$next($request)来传递对象,而写入$next($request)意味着执行这个闭包,也就是函数A,然后返回函数B,可以传递给下一个中间件。
为了简化代码:
//这里的$stack实际上是一个闭包。$firstSlice的闭包会在第一次遍历中传递,以后每次都会传入下面的函数;而$pipe就是每个中间件的array _ reduce ($ pipes),function ($ stack,$ pipe){ return function($ passable)use($ stack,$ pipe){ };},$ First slice);让我们看看这段代码:
//判断是否是闭包,这里是判断中间件表单是否是闭包,如果是,直接执行,传入$passable[ Request Instance]和$stack[传到下一个中间件闭包],返回if($ Closure的Pipe Instance){ Return Call _ User _ func($ Pipe,$passable,$ Stack);//当不是闭包时,是这样的:illuminate \ foundation \ http \ middleware \ checkformaintancemode执行} else {//解析,返回名称。这个$parameters看了很久也看不懂源代码。它应该与参数有关,但不影响我们的分析列表($ name,$ parameters)=$ this-parsepestring//从容器中解析中间件实例并执行handle方法returncall _ user _ func _ array([$ this-container-make($ name),$ this-method],/$ passable是请求实例,$stack是传递的闭包数组_ merge ([$ passable,$ stack],$ parameters) }再看一张图片:
每次迭代都会引入最后一个要执行的闭包和中间件。因为数组是反向的,基于栈先入后出的特点,先封装中间件3,中间件1在最外层。请记住,arrary _ reduce不执行中间件代码,而是包装中间件。
需要理解的是,array_reduce最终会返回func3,所以call _ user _ func (func3,$ this-passable)实际上是复制代码如下: return call _ user _ func($ middleware[0]-handle,$ this-passable,func 2);
我们中间件中的句柄代码是:
公共函数句柄($request,Closure $ next){ return $ next($ request);}这里相当于返回func2($request),其中$request由最后一个中间件处理。所以中间件的过程就完成了,理解起来会有点混乱,只要记住中间件代码是由最外层的call_user_func执行就可以了。
更多对Laravel感兴趣的读者可以查看本网站的话题:《Laravel框架入门与进阶教程》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php日期与时间用法总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》、《php常见数据库操作技巧汇总》、0103010。
希望本文对基于Laravel框架的PHP编程有所帮助。
版权声明:Laravel中间件实现原理详解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。