Lumen 使用 dingo/api 的第一步便是
$app->register(Dingo\Api\Provider\LumenServiceProvider::class);
,所以就从这个文件说起吧。
这个文件的父类是
\Dingo\Api\Provider\DingoServiceProvider
,我们可以在这个文件中发现其注册了很多的东西到
App 容器里面,其中也有很多单例的对象等等等等,
但是,这些都不重要,重要的是 ::boot
方法里面的处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public function boot ( ) { parent ::boot (); $this ->app->configure ('api' ); $reflection = new ReflectionClass ($this ->app); $this ->app[Request ::class ]->mergeMiddlewares ( $this ->gatherAppMiddleware ($reflection ) ); $this ->addRequestMiddlewareToBeginning ($reflection ); $this ->app->rebinding (IlluminateRequest ::class , function ($app , $request ) { $request ->setRouteResolver (function () use ($app ) { $reflection = new ReflectionClass ($app ); $property = $reflection ->getProperty ('currentRoute' ); $property ->setAccessible (true ); return $property ->getValue ($app ); }); }); $this ->app->routeMiddleware ([ 'api.auth' => Auth ::class , 'api.throttle' => RateLimit ::class , 'api.controllers' => PrepareController ::class , ]); }
到此为止,我们已经知道,我们的请求会先经过
\Dingo\Api\Http\Middleware\Request
中间件处理,这是很关键的一步,接下来,我们看看这个中间件做了什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public function handle ($request , Closure $next ) { try { if ($this ->validator->validateRequest ($request )) { $this ->app->singleton (LaravelExceptionHandler ::class , function ($app ) { return $app [ExceptionHandler ::class ]; }); $request = $this ->app->make (RequestContract ::class )->createFromIlluminate ($request ); $this ->events->fire (new RequestWasMatched ($request , $this ->app)); return $this ->sendRequestThroughRouter ($request ); } } catch (Exception $exception ) { $this ->exception->report ($exception ); return $this ->exception->handle ($exception ); } return $next ($request ); }
最后一步,也是很关键的一步:
在所有中间件处理完之后,会把 $request 传递给
\Dingo\Api\Routing\Router::dispatch
处理,
处理完成后,使用
\Dingo\Api\Routing\Router::prepareResponse
处理控制器方法返回的响应结果
这是 dingo/api transformer include 操作实际执行的地方,
也许我们都曾经有过这样的疑惑:include 到底是在哪里进行数据库查询的?
其实是在这个方法里面执行的,具体细节有兴趣的执行研究。
这也算是 dingo 的一个特性了,但是 include 有太多坏处了,例如
N+1,但是也还是有解决方法的,不用 include... 还有嵌套 include
导致代码难以维护等等