Laravel 之路由分發

Dennis_Ritchie發表於2019-12-24

前言

在閱讀這篇文章之前,希望你閱讀過了我之前寫過的一系列的文章,但最起碼閱讀過這篇《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,所以請檢視你的版本。學習需要堅持,才能成就非凡。學習交流群:

如果有不懂的地方,可以加我的qq:1174332406,或者是微信:itshardjs

相關文章