老王,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 返回了一个匿名回调函数。使用 Kernel 的 route 属性进行调度。
Kernel 的 route 是一个 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’] 。当我们第二参数是一个字符串的时候则认为是控制器方法,将请求转发到控制器里去处理。否则执行回调函数处理。
到这里,我们的请求就真的到达了我们的控制器的方法中,开始执行我们写的代码了。