资讯专栏INFORMATION COLUMN

illuminate/routing 源码分析之注册路由

seal_de / 3392人阅读

摘要:本文将会源码分析下是如何把开发者在中写的路由列表注册到对象内的。通过以上的分析,就能对路由系统的基本设计越来越清晰。一个进来后,首先开始启动并按照以上逻辑开始注册路由列表,然后就是根据当前信息查找对应的对象。

我们知道,在 Laravel 世界里,外界传进来一个 Request 时,会被 Kernel 处理并返回给外界一个 Response。Kernel 在处理 Request 时,会调用 illuminate/routing 包提供的路由功能,来根据当前的 Request,转发到对应的执行逻辑(执行逻辑的形式可以为 Closure 或 Controller@Action)。同时,在进入执行逻辑之前和之后,还会依次进入 Middlewares 的前置和后置处理。所以,一个 Request 由 Kernel 处理为一个 Response 的一个生命周期图如下:

根据上面的流程,理解路由系统的内部工作原理是非常重要的!当然,它也是非常复杂的。想要深入理解一个工具的使用,学习它的内部设计原理才是画龙点睛。在理解 illuminate/routing 如何工作之前,先设想如何去设计一个路由系统呢?一起想个三分钟吧。

注册路由 :想想一个 Request 进入程序时,携带的请求信息类似为 GET https://localhost/api/v2/peop...,所以我们需要定义一个 Route 对象来表示这个信息,同时还得定义 RouteCollection(Route 的集合)来添加、获取和匹配出一个 Route。程序启动时,开发者定义的所有路由(Route)列表都会被注册到 RouteCollection 内。

查找路由 :有了整个程序的路由列表,这样当一个 Request 进来时,再根据当前 Request 的信息匹配出一个合适的 Route,所以可以设计一个类似 RouterManager 对象,作用类似开发经理 Manager 的总体统筹,来调用 $router->findRoute($request): Route 匹配出合适的 Route。

运行路由 :既然匹配出了对应 Route,那可以调用 RouterManager->runRoute($route): Response 得到对应的 Response 返回给外界。

所以,如果自己去设计一个路由系统,就可以按照上面三步去做,思路也很好理解。实际上,Laravel 的路由模块 illuminate/routing 也是按照这三个步骤来设计的。本文将会源码分析下 Laravel 是如何把开发者在 routes/*.php 中写的路由列表注册到 RouteCollection 对象内的。

我们知道,Laravel 在启动时第一步会去实例化 IlluminateFoundationApplication 对象,这个容器对象会去调用 IlluminateRoutingRoutingServiceProvider::register() 往容器对象的 $bindings 数组属性key-value 形式注册进来,注册的对象主要包括 Router(就是上文的 RouterManager 角色,把它比作为开发小组的开发经理角色)等。

然后会去调用 AppProvidersRouteServiceProvider::boot() 方法默认加载 routes/api.php 和 routes/web.php 文件中注册的路由列表,并且以 Facade 模式去注册路由列表:

Route::prefix($prefix)->middleware($middleware)->group("xxx/web.php");

实际上就是调用 IlluminateRoutingRouteRegistrar 类里的 attribute(key, value) 方法以 key-value 形式注册到 attributes 数组属性里。最主要的 group(string) 方法调用的是 Router::group() 方法,然后调用 loadRoutes(routes) 去执行在 routes/api.php 和 routes/web.php 文件中定义的路由。对于每一种方法(如 GET、POST 等等方法)的路由,Router 对象内都有对应的方法来添加 Route 注册到 RouteCollection 中,比如常见的 get(uri, action) 方法,就是调用的 RouteCollection::add(route) 方法把 Route 注册到 RouteCollection 中。而 route 的创建,调用的是 Router::createRoute(methods, uri, action),其中由于 $action 可能是 Closure 或者 Controller@Action,如果是 Controller@Action 形式,则需要把字符串切割为数组形式,再传入 Route 类的构造函数里。

总结下注册路由所需要用到的对象:使用 Route 来表示路由信息,使用 RouteCollection 来表示路由集合列表,并且提供了添加删除方法来把 Route 注册到 RouteCollection 内,而 Router 才是纵览全局的角色,注册路由是通过该对象发起的,它会调用 RouteCollection 去注册路由,路由的元数据信息如路由名称等是用 RouteRegistrar 对象表示。从上文可知道,所有对象中,Router 才是画龙点睛的对象。

通过以上的分析,就能对 illuminate/routing 路由系统的基本设计越来越清晰。一个 Request 进来后,Application 首先开始启动并按照以上逻辑开始注册路由列表,然后就是根据当前 Request 信息查找对应的 Route 对象。

那如何根据当前 Request 信息查找出对应的 Route 的呢?见本系列第二篇文章。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29159.html

相关文章

  • Laravel中你为什么可以直接在 web.php 中 直接使用 Route ? 服务提供者的介绍

    摘要:这篇文章来自一个社区问题的思考中为什么可以直接使用原理很简单首先你注意一下里面 这篇文章来自一个 sf 社区问题的思考 laravel web.php 中 Route 为什么可以直接使用 原理很简单 1 . 首先, 你注意一下 /config/app.php 里面 /* |----------------------------------------------------...

    desdik 评论0 收藏0
  • laravel auth 认证

    摘要:如果两个经哈希运算的密码相匹配那么将会为这个用户开启一个认证。如果认证成功的话方法将会返回。重定向器上的方法将用户重定向到登录之前用户想要访问的,在目标无效的情况下回退将会传递给该方法。最后如有错误,欢迎指出交流群 Auth认证 路由 从路由开始,找到源码,再进行研究找到根目录下面的 vendor/laravel/framework/src/Illuminate/Routing/Rou...

    Lionad-Morotar 评论0 收藏0
  • laravel Route::controller 使用路由命名

    摘要:我们知道,在中使用的话,只需要绑定模型,在创建表单,链接时,直接可以拿来用,不需要单独的去给路由别名如创建链接但是我们使用时,在创建链接,尝试用以上方法访问时,就会报错如创建链接抛出路由不存在的错误那我们如何像使用一样方便的来使用呢很简单, 我们知道,在 laravel 中使用 resource 的话,只需要绑定模型,在创建表单,链接时,直接可以拿来用,不需要单独的去给路由 as 别名...

    tracymac7 评论0 收藏0
  • Laravel 5.5 升级到 5.5.42 后遇到的 Cookie 序列化问题

    摘要:查阅官方文档后得知,新版为了防止对象的序列化反序列化漏洞被利用,不再对值进行自动的序列化和反序列化处理。举个栗子更新到后,因为不再自动对值进行序列化处理,而只能加密字符串数据,这个时候程序就会抛出错误。 最近手残升级了项目里 Laravel 的小版本号(v5.5.39 => v5.5.45),这不升级则已,一升级就出了问题! Sentry 平台上提示错误:openssl_encrypt...

    jollywing 评论0 收藏0
  • Laravel 依赖注入源码解析

    在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如: public function store(Request $request) { //TODO } 这里 $request 参数就使用了类型约束,Request 是类型约束的类型,它是一个类:IlluminateHttpRequest. 本文研究 Laravel 的依赖注入原理,为什么这样定义...

    Donne 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<