本页目录
Router 如何匹配并执行路由
入口来自 HTTP Kernel 的 dispatchToRouter():
入口来自 HTTP Kernel 的 dispatchToRouter():
$router->dispatch($request)
文件:vendor/laravel/framework/src/Illuminate/Routing/Router.php
Router::dispatch
执行两步:
$this->currentRequest = $request保存当前请求。return $this->dispatchToRoute($request)。
dispatchToRoute
runRoute($request, findRoute($request))
也就是先找路由,再运行路由。
findRoute
findRoute($request) 做这些事:
- 派发
Routing事件。 $this->routes->match($request)从路由集合中找匹配项。- 把匹配到的 route 存到
$this->current。 - 给 route 设置容器。
- 把
Illuminate\Routing\Route::class实例放入容器。 - 返回 route。
RouteCollection::match
文件:Illuminate\Routing\RouteCollection
match 的逻辑:
- 根据请求方法取候选路由,例如 GET 请求取 GET 路由表。
matchAgainstRoutes遍历候选路由,调用$route->matches($request)。- 找到匹配路由后,
handleMatchedRoute调用$route->bind($request)。 - 如果当前方法没有匹配,但其他 HTTP 方法匹配同一路径,则抛 Method Not Allowed。
- 如果完全没匹配,抛 Not Found。
对于 GET /,它会匹配 routes/web.php 注册的 / 路由。
runRoute
找到 route 后,runRoute($request, $route) 做:
- 给 Request 设置 route resolver。之后
$request->route()可以拿到当前 route。 - 派发
RouteMatched事件。 - 调用
runRouteWithinStack($route, $request)。 - 把结果交给
prepareResponse转成标准 Response。
runRouteWithinStack
这里是路由中间件管道:
- 判断是否禁用中间件。
- 收集当前 route 的中间件。当前
/路由来自web组。 - 创建
Illuminate\Routing\Pipeline。 - 请求穿过路由中间件。
- 最后执行
$route->run()。
Route::run
文件:Illuminate\Routing\Route
当前路由 action 是闭包,不是控制器,所以:
runCallable()
runCallable() 会取出保存的闭包,然后通过容器里的 CallableDispatcher 执行。
CallableDispatcher::dispatch
文件:Illuminate\Routing\CallableDispatcher
它会:
- 根据闭包参数和路由参数解析依赖。
- 调用闭包。
当前闭包没有参数,所以直接执行:
return view('welcome');
下一章进入视图:view('welcome') 到 HTML