老王,Laravel的請求怎麼一步步到達控制器的?
- 2019 年 10 月 4 日
- 筆記
老王啊,你能不能跟我解釋一下,一個請求怎麼一步步到達控制器的,中間都經歷了哪些東西,以Laravel5.8為例。
入口
Laravel5.8 入口文件為public/index.php

創建了一個Kernel對象,調用handler處理請求,獲取返回結果。將返回結果輸出到客戶端,處理terminate操作。
Kernel中如何處理請求
容器里綁定的是AppHttpKernel,繼承於IlluminateFoundationHttpKernel。

Kernel中調用sendRequestThroughRouter方法,將請求傳遞到路由處理當中。

在sendRequestThroughRouter當中,在app中綁定了request實例,並解綁掉其他request實例對象。這樣在程式其他地方都能通過app()->make('request')獲取到request實例對象。
調用bootstrap方法,載入引導類。
創建一個Pipeline對象,將路由調度與中間件放入調用鏈當中。所有request先經過全局的中間件,然後在通過路由分發。

因為Piepline調用鏈都是一個個的回調方法,所以在dispatchToRouter返回了一個匿名回調函數。使用Kernel的route屬性進行調度。
Kernel的route是一個IlluminateRoutingRouter對象。
路由調度

從上面的方法可以看出,最終通過findRoute查找當前匹配的路由對象,並調用runRoute處理請求返回結果。
怎麼找到路由的

對路由的匹配,是通過routes這個路由Collections去匹配的。

先通過請求的方法獲取當前方法下可用的路由集合,在從這些集合中去遍歷獲取第一個匹配的路由。集合中每個item是一個IlluminateRoutingRouter對象。因此最終判斷路由與請求是否匹配調用的是IlluminateRoutingRouter中的matches方法。

在IlluminateRoutingRouter提供了四個默認的驗證器,當四個驗證器通過的時候才會匹配成功。四個驗證器分別是UriValidator驗證訪問路徑,MethodValidator驗證請求方法,SchemeValidator驗證訪問協議,HostValidator驗證域名。其中對uri的驗證內部是使用正則表達式驗證。
路由調度怎麼處理請求


路由對請求的處理也是返回一個Pipeline,先將請求通過中間件,然後在執行路由的run方法。在run方法裡面判斷當前是執行控制器方法還是回調方法,根據不同類型分開執行。
怎麼執行

通過當前路由的action配置判斷是否是控制器或者回調方法。從程式碼中可以看到,其實就是我們路由配置中的第二個參數對應到action['user']。當我們第二參數是一個字元串的時候則認為是控制器方法,將請求轉發到控制器里去處理。否則執行回調函數處理。
到這裡,我們的請求就真的到達了我們的控制器的方法中,開始執行我們寫的程式碼了。