Laravel 之路由分发

前言

在阅读这篇文章之前,希望你阅读过了我之前写过的一系列的文章,但最起码阅读过这篇《Laravel 之路由匹配》,老人常说师傅领进门,修行靠个人,我也只能带大家整理思路,而忽略了一些细节,这是锻炼你自己的好机会。

代码分析

我们从Illuminate\Foundation\Http\Kernel类开始进行分析,如果你不知道为什么,请阅读《Laravel 之路由匹配》。

Laravel之路由分发

全局中间件运行完之后,就会调用dispatchToRouter方法返回的回调:

Laravel之路由分发

这里的router指的是Illuminate\Routing\Router类的实例,我们看它的dispatch方法:

Laravel之路由分发

方法dispatchToRoute被调用:

Laravel之路由分发

在上一篇《Laravel 之路由匹配》中,我们已经讨论过了findRoute了,我们本节的重点是runRoute也就是路由分发。

Laravel之路由分发

runRoute方法中,我们关心的重点是红色标出来的部分,我们直接分析runRouteWithinStack方法:

Laravel之路由分发

第一部分,判断是否需要忽略路由中间件,这取决于我们是否向容器中注册了middleware.disable,如果注册了并且为true的话,就会忽略我们设置的路由中间件。

我们分析需要路由中间件的情况,所以接下来调用gatherRouteMiddleware方法:

Laravel之路由分发

这个方法的作用是收集匹配路由的中间件,进入到该函数中一探究竟,代码1(图中标出来的)调用Illuminate\Routing\Route实例的gatherMiddleware方法,在前面的文章中,我已经给大家解释过了,Laravel中每一条路由都是Illuminate\Routing\Route类的对象。

Laravel之路由分发

这里首先调用middleware方法,这个方法返回的值为我们注册路由的时候设置的中间价,比如通过以下方式:

Laravel之路由分发

controllerMiddleware方法,这个方法很重要:

Laravel之路由分发

为了更能突出问题的重点,我会忽略掉一些很简单的方法调用,这里的isControllerAction方法判断当前路由是否对应一个控制器,比如你可能有这样的路由'HomeController@index',那么这个路由对应的就是控制器,getController方法返回当前路由的控制器类,getControllerMethod返回控制器方法,在我们的例子中控制器和方法分别是HomeControllerindex

我们再来分析controllerDispatcher方法,从它的名字就可以看出它是控制器分发器,我们看下他的代码:

Laravel之路由分发

关于这个方法上面的代码,你可以假设不存在(实际上你确实可以这么做),继续分析,直接生成了Illuminate\Routing\ControllerDispatcher类的对象,回到路由对象中controllerMiddleware中,调用了Illuminate\Routing\ControllerDispatcher类的getMiddleware方法,我们来看这个方法:

Laravel之路由分发

这里判断控制器是否存在getMiddleware方法,这个方法会返回一系列路由中间件,至于返回的格式,你可以查看Illuminate\Routing\ControllerDispatcher类的methodExcludedByOptions方法。

经过上面的分析,我们返回到Route类的gatherMiddleware方法,这个方法合并我们上面提到的中间件并返回,紧接着从Router类的gatherRouteMiddleware方法返回,继续返回到 runRouteWithinStack方法中:

Laravel之路由分发

关于管道,我在之前的文章《老司机带你深入理解 Laravel 中间件(全局中间件)》中仔细讲过了,这里的管道操作运行所有的当前路由的中间件,中间件运行完之后,出发红色标出来的代码,也就是调用当前路由的run方法,

Laravel之路由分发

1是运行控制器,2是运行回调方法,这里我们运行控制器,那么就会调用runController方法:

Laravel之路由分发
Illuminate.outing.ontrollerDispatcher类的dispatch方法被调用:

Laravel之路由分发

第1部分解析控制器方法的依赖性,第2部分检查当前控制器是否存在callAction,如果存在就调用它,当然一般的情况,代码3会直接被调用,比如对于上面的HomeController来说,index方法就被调用了。

总结

上面简要的给大家梳理了Laravel路由分发的过程,我忽略了一些不那么重要的内容,希望大家仔细去看,提醒大家一句,我分析的代码版本为5.8,所以请查看你的版本。学习需要坚持,才能成就非凡。学习交流群:

本作品采用《CC 协议》,转载必须注明作者和本文链接
微信:okayGoHome
本帖由系统于 5年前 自动加精
Dennis_Ritchie
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

mark后看.

5年前 评论

大佬真的厉害了,对laravel框架源码分析的很透彻,以前觉得框架源码很神秘,现在看来其实也没有想象中的复杂,可能是以前不懂那些设计模式,比如外观模式,装饰者模式,容器技术,这才是框架的核心

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!