老王,Laravel的请求怎么一步步到达控制器的?

老王啊,你能不能跟我解释一下,一个请求怎么一步步到达控制器的,中间都经历了哪些东西,以Laravel5.8为例。

入口

Laravel5.8 入口文件为 public/index.php

创建了一个 Kernel 对象,调用handler处理请求,获取返回结果。将返回结果输出到客户端,处理 terminate 操作。

Kernel中如何处理请求

容器里绑定的是 App\Http\Kernel ,继承于 Illuminate\Foundation\Http\Kernel

Kernel中调用 sendRequestThroughRouter 方法,将请求传递到路由处理当中。

sendRequestThroughRouter 当中,在app中绑定了 request 实例,并解绑掉其他request实例对象。这样在程序其他地方都能通过 app()->make(‘request’) 获取到request实例对象。

调用 bootstrap 方法,加载引导类。

创建一个 Pipeline 对象,将路由调度与中间件放入调用链当中。所有request先经过全局的 中间件 ,然后在通过路由分发。

因为 Piepline 调用链都是一个个的回调方法,所以在 dispatchToRouter 返回了一个匿名回调函数。使用 Kernelroute 属性进行调度。

Kernelroute 是一个 Illuminate\Routing\Router 对象。

路由调度

从上面的方法可以看出,最终通过 findRoute 查找当前匹配的路由对象,并调用 runRoute 处理请求返回结果。

怎么找到路由的

对路由的匹配,是通过 routes 这个路由 Collections 去匹配的。

先通过请求的方法获取当前方法下可用的路由集合,在从这些集合中去遍历获取第一个匹配的路由。集合中每个 item 是一个 Illuminate\Routing\Router 对象。因此最终判断路由与请求是否匹配调用的是 Illuminate\Routing\Router 中的matches方法。

Illuminate\Routing\Router 提供了四个默认的验证器,当四个验证器通过的时候才会匹配成功。四个验证器分别是 UriValidator 验证访问路径, MethodValidator 验证请求方法, SchemeValidator 验证访问协议, HostValidator 验证域名。其中对 uri 的验证内部是使用正则表达式验证。

路由调度怎么处理请求

路由对请求的处理也是返回一个 Pipeline ,先将请求通过中间件,然后在执行路由的 run 方法。在 run 方法里面判断当前是执行控制器方法还是回调方法,根据不同类型分开执行。

怎么执行

通过当前路由的 action 配置判断是否是控制器或者回调方法。从代码中可以看到,其实就是我们路由配置中的第二个参数对应到 action[‘user’] 。当我们第二参数是一个字符串的时候则认为是控制器方法,将请求转发到控制器里去处理。否则执行回调函数处理。

到这里,我们的请求就真的到达了我们的控制器的方法中,开始执行我们写的代码了。