前言
在閱讀這篇文章之前,希望你閱讀過了我之前寫過的一系列的文章,但最起碼閱讀過這篇《Laravel 之路由匹配》,老人常說師傅領進門,修行靠個人,我也只能帶大家整理思路,而忽略了一些細節,這是鍛鍊你自己的好機會。
程式碼分析
我們從Illuminate\Foundation\Http\Kernel
類開始進行分析,如果你不知道為什麼,請閱讀《Laravel 之路由匹配》。
當全域性中介軟體執行完之後,就會呼叫dispatchToRouter
方法返回的回撥:
這裡的router
指的是Illuminate\Routing\Router
類的例項,我們看它的dispatch
方法:
方法dispatchToRoute
被呼叫:
在上一篇《Laravel 之路由匹配》中,我們已經討論過了findRoute
了,我們本節的重點是runRoute
也就是路由分發。
runRoute
方法中,我們關心的重點是紅色標出來的部分,我們直接分析runRouteWithinStack
方法:
第一部分,判斷是否需要忽略路由中介軟體,這取決於我們是否向容器中註冊了middleware.disable
,如果註冊了並且為true的話,就會忽略我們設定的路由中介軟體。
我們分析需要路由中介軟體的情況,所以接下來呼叫gatherRouteMiddleware
方法:
這個方法的作用是收集匹配路由的中介軟體,進入到該函式中一探究竟,程式碼1(圖中標出來的)呼叫Illuminate\Routing\Route
例項的gatherMiddleware
方法,在前面的文章中,我已經給大家解釋過了,Laravel中每一條路由都是Illuminate\Routing\Route
類的物件。
這裡首先呼叫middleware
方法,這個方法返回的值為我們註冊路由的時候設定的中間價,比如通過以下方式:
controllerMiddleware
方法,這個方法很重要:
為了更能突出問題的重點,我會忽略掉一些很簡單的方法呼叫,這裡的isControllerAction
方法判斷當前路由是否對應一個控制器,比如你可能有這樣的路由'HomeController@index'
,那麼這個路由對應的就是控制器,getController
方法返回當前路由的控制器類,getControllerMethod
返回控制器方法,在我們的例子中控制器和方法分別是HomeController
和index
。
我們再來分析controllerDispatcher
方法,從它的名字就可以看出它是控制器分發器,我們看下他的程式碼:
關於這個方法上面的程式碼,你可以假設不存在(實際上你確實可以這麼做),繼續分析,直接生成了Illuminate\Routing\ControllerDispatcher
類的物件,回到路由物件中controllerMiddleware
中,呼叫了Illuminate\Routing\ControllerDispatcher
類的getMiddleware
方法,我們來看這個方法:
這裡判斷控制器是否存在getMiddleware
方法,這個方法會返回一系列路由中介軟體,至於返回的格式,你可以檢視Illuminate\Routing\ControllerDispatcher
類的methodExcludedByOptions
方法。
經過上面的分析,我們返回到Route
類的gatherMiddleware
方法,這個方法合併我們上面提到的中介軟體並返回,緊接著從Router
類的gatherRouteMiddleware
方法返回,繼續返回到 runRouteWithinStack
方法中:
關於管道,我在之前的文章《老司機帶你深入理解 Laravel 中介軟體(全域性中介軟體)》中仔細講過了,這裡的管道操作執行所有的當前路由的中介軟體,中介軟體執行完之後,出發紅色標出來的程式碼,也就是呼叫當前路由的run
方法,
1是執行控制器,2是執行回撥方法,這裡我們執行控制器,那麼就會呼叫runController
方法:
Illuminate.outing.ontrollerDispatcher
類的dispatch
方法被呼叫:
第1部分解析控制器方法的依賴性,第2部分檢查當前控制器是否存在callAction
,如果存在就呼叫它,當然一般的情況,程式碼3會直接被呼叫,比如對於上面的HomeController
來說,index
方法就被呼叫了。
總結
上面簡要的給大家梳理了Laravel路由分發的過程,我忽略了一些不那麼重要的內容,希望大家仔細去看,提醒大家一句,我分析的程式碼版本為5.8,所以請檢視你的版本。學習需要堅持,才能成就非凡。學習交流群: