保护私人版权,尊重他人版权。转载请注明出处并附带页面链接
本文从Lumen的源码入手,说一下Request -> Response 的解析过程,这里用到的是Lumen5.8
入口
bootstrap/app.php
1 | $app->router->group([ |
先从Lumen的入口文件开始,这里可以看到我们的router变量,router就是负责将我们的method
、uri
、action
关联起来,用于解析Request
那么接下来看一下router是从哪里来的:
vendor/laravel/lumen-framework/src/Application.php
1 |
|
可以看到$this->router = new Router($this)
这一句实例化了router,由此我们定位到了router所在位置vendor/laravel/lumen-framework/src/Routing/Router.php
group
还记得我们的入口里的router用到了group方法吗?我们来看一下group相关源码:
1 | /** |
先判断attributes
中有无中间件middleware,有的话就解析成数组,并合并到$this->groupStack中。
这里看到middleware的解析方式,可以知道传入多个中间件的时候,除了按照官方文档'middleware' => ['auth1','auth2']
这种方式外,还可以用middleware' => 'auth1|auth2'
的写法,效果是一样的。
往下看,我们看到执行了call_user_func($callback, $this),即:
1 | function ($router) { |
这里会把web.php
加载进来,相当于:
1 | function ($router) { |
addRoute
接着看get
、post
函数,发现它们的本质都是调addRoute
:
1 | /** |
首先是parseAction:
1 |
|
这里将$action
转为数组,对中间件的处理也是上面一样的
继续往下看
1 | if (isset($attributes) && is_array($attributes)) { |
这里是拼接uri的前缀和后缀,并且将attributes
合并到$action
1 |
|
这里首先保存命名路由到namedRoutes中,命名路由可以方便的为特定路由生成 URL 或进行重定向,使用方式如下:
1 | $router->get('profile', [ |
1 | if (is_array($method)) { |
最后就是把method
、uri
、action
存到routes中了,这里看到$method
可以是一个数组,也就是说我们可以这样定义允许多个请求方法的路由:
1 | $this->addRoute(['GET','POST'], $uri, $action); |
Request
public/index.php 可以看到Lumen的入口方法:
1 | $app = require __DIR__.'/../bootstrap/app.php'; |
定位到vendor/laravel/lumen-framework/src/Application.php:
1 | use Concerns\RoutesRequests, |
从而找到run方法所在文件vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php:
1 |
|
先看dispatch函数:
1 |
|
首先拿到请求方式$method和请求路径$pathInfo,然后我们看到代理中会有三个返回,1是最外层的,最后再看,这里先看3
3这里的dispatch返回的数据结构如下:
1 | interface Dispatcher |
接着看一下createDispatcher:
1 |
|
simpleDispatcher这个方法主要是创建 routeCollector
对象,用于存储所有 route
再看循环里的addRoute方法,这里用到的是vendor/nikic/fast-route/src/RouteCollector.php:
1 |
|
继续看$this->dataGenerator->addRoute($method, $routeData, $handler)
,vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php:
1 |
|
这里是对普通的路由和正则路由分别处理
然后回到$this->handleDispatcherResponse这里:
1 |
|
可以看到找不到路由或者请求方法不允许都会抛异常,继续看handleFoundRoute
1 |
|
这里不看中间件,直接看最后的callActionOnArrayBasedRoute:
1 | /** |
先看callControllerAction:
1 |
|
这里通过@
来分解controller
和method
,再用$this->make($controller)
得到Controller
对象,如果是LumenController类型,则会对中间件做一些判断,最后都是调用callControllerCallable方法
Response
最后看prepareResponse方法
1 |
|
这里就回到了我们一开始的run方法
1 |
|
至此,我们的请求到响应就走完了
总结
本文只是对Request到Response的相关源码走了一遍流程,对于一些细节的东西没有深挖,但是从源码中也能学到不少东西,比如uri支持多种请求方式,比如用$this->make处理route等