Laravel 之路由执行原理
参考
路由加载原理
- 在 Laravel 中,所有的服务都是通过
服务提供者
的register
方法绑定到Laralvel 服务容器
中,之后才可以在 Laravel 项目中使用。 - 加载路由文件任务本质是一种服务,它实现的功能是将路由文件中定义的路由加载到 Laravel 内核中。
- 然后再去匹配正确的路由并处理 HTTP 请求。所以,这里我们应该查找到与路由有关的
服务提供者
去注册和启动路由相关服务。
config/app.php
配置文件中的providers
中的App\Providers\RouteServiceProvider::class
。- 服务提供者的注册和启动处理由
Illuminate\Foundation\Http\Kernel
这个HTTP
内核程序完成。
简单介绍下服务提供者的加载和执行过程
- 首先,HTTP 内核程序会去执行所有服务提供者的
register
方法,将所有的服务注册到服务容器内,这里的注册指的是将服务绑定(bind
)到容器。 - 当所有服务提供者注册完后,会执行已完成注册服务提供者的
boot
方法启动服务。
路由服务提供者启动过程总结起来一共分为以下几个步骤
- 将我们 Laravel 应用的控制器所在的命名空间设置到 URL 生成器中(UrlGenerator)供后续使用。
- 处于系统性能上的考量,会率先检测是否启用路由缓存。已缓存路由的话直接从缓存文件中读取路由配置。
- 未缓存则由
loadRoutes
方法执行缓存处理。最终会到由App\Providers\RouteServiceProvider
类中定义的map
方法执行路由载入处理。
处理 Web 路由加载时
通过 Route 门面(Facade
)所代理的 Illuminate\Routing\Router
服务依次执行。
- 执行
Route::middleware('web')
将web 中间件
注册到路由。 - 执行
namespace($this->namespace)
方法,将控制器命名空间设置到路由中。 - 最后执行以路由文件
base_path('routes/web.php')
目录为参数的group
方法完成 Web 路由组的设置。
- 在 Laravel 中门面是一种提供了操作简单的能够使用静态方法来方式访问 Laravel 服务的机制。
最终
在 Illuminate\Routing\Router::group
方法里去执行路由文件引入处理。
- 通过
updateGroupStack
方法,更新路由组中的属性,即由Route::middleware(...)->namespace(...)
设置的中间件和命名空间等。 - 使用
loadRoutes
方法引入base_path('routes/web.php')
文件中定义的路由。
- 简短截说,最终在
RouteRegistrar::group
方法内部完成对Illuminate\Routing\Router::group
方法的调用,实现载入路由文件处理。
处理整个 HTTP 请求的过程分完几个阶段
- 清空已解析的请求(clearResolvedInstance)。
- 执行应用的引导程序(bootstrap)。
- 将请求发送到中间件和路由中,这个由管道组件完成(Pipeline)。
路由分发流程
Illuminate\Routing\Router
服务将接收被分发到的请求($request),然后执行路由设置是配置的闭包(或控制器)函数,整个过程包括:
- 从
RouteCollection
路由集合中查找出当前请求 URI( r e q u e s t )匹配的路由,由 ‘ R o u t e r : : f i n d R o u t e ( request)匹配的路由,由 `Router::findRoute( request)匹配的路由,由‘Router::findRoute(request)` 方法完成。 - 运行路由配置阶段所配置的闭包(或控制器方法),这个处理在
Router::runRoute(Request $request,Route $route)
方法完成。- 在运行路由闭包或控制器方法时,将采用类似
HTTPkernel
的handle
执行方式去运行当前路由适用的局部中间件。 - 在最终的
then
方法内部会执行$route->run()
方法运行路由,$route(Illuminate\Routing\Route)
为findRoute
方法查找到的路由。
- 在运行路由闭包或控制器方法时,将采用类似
- 生成 HTTP 响应(由
prepareResponse
方法完成)。
总结
- Laravel 中的路由如何被加载到项目中。
- 如何接收 HTTP 请求。
- 如何依据 HTTP 请求($request)查找所匹配的路由。
- 运行路由闭包或控制器方法。