分析 Lumen Application--dispatch() 下篇

继续看 RoutesRequests 下面的方法:

  • createDispatcher()
  • sendExceptionToHandler()
  • prepareResponse()

createDispatcher()

Lumen 并没有使用 Laravel 的 Routing,而是使用自定义的 Router,把 Router 和 FastRoute 结合的就是这个方法:

protected function createDispatcher()
{
    return $this->dispatcher ?: \FastRoute\simpleDispatcher(function ($r) {
        foreach ($this->router->getRoutes() as $route) {
            $r->addRoute($route['method'], $route['uri'], $route['action']);
        }
    });
}

simpleDispatcher 是 FastRoute 提供 Dispatcher 的工厂方法。传入的 $r 会是 FastRoute 专用的 RouteCollection。可以看到它使用 addRoute() 把 Lumen Router 存放的 Route 再转存到 FastRoute Collection 里。

最后 dispatcher 属性,将会是 FastRoute 的 Dispatcher。

sendExceptionToHandler()

protected function sendExceptionToHandler($e)
{
    // 这里将会取得 ExceptionHandler 实例
    $handler = $this->resolveExceptionHandler();

    // 转换 Error 为 FatalThrowableError
    if ($e instanceof Error) {
        $e = new FatalThrowableError($e);
    }

    // 这里的 report 与 render 和 Laravel 的使用方法大同小异
    $handler->report($e);

    return $handler->render($this->make('request'), $e);
}

Laravel 的 ErrorHandler 分析可以参考 Day31 分析自定义错误页

prepareResponse()

Laravel 也有 prepareResponse(),Lumen 就像是精简版一样:

public function prepareResponse($response)
{
    $request = app(Request::class);

    // 转换 Responsable
    if ($response instanceof Responsable) {
        $response = $response->toResponse($request);
    }

    // 转换 PSR7 Response
    if ($response instanceof PsrResponseInterface) {
        $response = (new HttpFoundationFactory)->createResponse($response);
        
    // 若不是 Symfony Response 的实例,则预期会是字符串,直接依字符串产生 response
    } elseif (! $response instanceof SymfonyResponse) {
        $response = new Response($response);

    // 转换 BinaryFileResponse
    } elseif ($response instanceof BinaryFileResponse) {
        $response = $response->prepare(Request::capture());
    }

    // 处理 Header 后回传
    return $response->prepare($request);
}

以上就是 dispatch() 详细分析的过程,接着明天再来看 Router 的实作。

发表评论