lumen5.5學習(三)

接着上篇$app->run();
--------------------分割線------------------------php

$app是Application的實例,可是Application.php文件中找不到run方法
在類內部看到use ConcernsRoutesRequests,打開找到了run方法,
run方法註釋寫的是主要用於運行應用以及發送響應web

/**
     * Run the application and send the response.
     *
     * @param  SymfonyRequest|null  $request
     * @return void
     */
    public function run($request = null)
    {
        $response = $this->dispatch($request);
        if ($response instanceof SymfonyResponse) {
            $response->send();
        } else {
            echo (string) $response;
        }

        if (count($this->middleware) > 0) {
            $this->callTerminableMiddleware($response);
        }
    }

主要看dispatch方法api

/**
     * Dispatch the incoming request.
     *
     * @param  SymfonyRequest|null  $request
     * @return Response
     */
    public function dispatch($request = null)
    {
        list($method, $pathInfo) = $this->parseIncomingRequest($request);
        try {
            return $this->sendThroughPipeline($this->middleware, function () use ($method, $pathInfo) {
                if (isset($this->router->getRoutes()[$method.$pathInfo])) {
                    return $this->handleFoundRoute([true, $this->router->getRoutes()[$method.$pathInfo]['action'], []]);
                }

                return $this->handleDispatcherResponse(
                    $this->createDispatcher()->dispatch($method, $pathInfo)
                );
            });
        } catch (Exception $e) {
            return $this->prepareResponse($this->sendExceptionToHandler($e));
        } catch (Throwable $e) {
            return $this->prepareResponse($this->sendExceptionToHandler($e));
        }
    }

由於請求的URL是 api.com/index.php/
$method.$pathInfo 打印出來是 array(1) { [0]=> string(4) "GET/" }
$this->router->getRoutes()是獲取在web.php定義的全部路由,返回的是一個數組形式的數據:數組

array (size=3)
  'GET/' => 
    array (size=3)
      'method' => string 'GET' (length=3)
      'uri' => string '/' (length=1)
      'action' => 
        array (size=1)
          0 => 
            object(Closure)[10]
              public 'static' => 
                array (size=1)
                  'router' => 
                    object(Laravel\Lumen\Routing\Router)[6]
                      public 'app' =>
                                ......

因此isset($this->router->getRoutes()[$method.$pathInfo]) 的結果就是 true
接着調用handleFoundRoute方法app

/**
     * Handle a route found by the dispatcher.
     *
     * @param  array  $routeInfo
     * @return mixed
     */
    protected function handleFoundRoute($routeInfo)
    {
        $this->currentRoute = $routeInfo;

        $this['request']->setRouteResolver(function () {
            return $this->currentRoute;
        });

        $action = $routeInfo[1];

        // Pipe through route middleware...
        if (isset($action['middleware'])) {
            $middleware = $this->gatherMiddlewareClassNames($action['middleware']);

            return $this->prepareResponse($this->sendThroughPipeline($middleware, function () {
                return $this->callActionOnArrayBasedRoute($this['request']->route());
            }));
        }

        return $this->prepareResponse(
            $this->callActionOnArrayBasedRoute($routeInfo)
        );
    }

若是有配置中間件的話還會有中間件的處理(後面再寫中間件的學習)
匹配到web.php裏面的這個路由後
看到這段代碼$this->callActionOnArrayBasedRoute($routeInfo)框架

/**
     * Call the Closure on the array based route.
     *
     * @param  array  $routeInfo
     * @return mixed
     */
    protected function callActionOnArrayBasedRoute($routeInfo)
    {
        $action = $routeInfo[1];

        if (isset($action['uses'])) {
            return $this->prepareResponse($this->callControllerAction($routeInfo));
        }

        foreach ($action as $value) {
            if ($value instanceof Closure) {
                $closure = $value->bindTo(new RoutingClosure);
                break;
            }
        }

        try {
            return $this->prepareResponse($this->call($closure, $routeInfo[2]));
        } catch (HttpResponseException $e) {
            return $e->getResponse();
        }
    }

裏面就是處理路由對應的響應方式,而且組裝響應數據準備返回學習

定義的路由是this

$router->get('/', function () use ($router) {
    return $router->app->version();
});

匹配到路由以後對應的處理是spa

function () use ($router) {
    return $router->app->version(); //'Lumen (5.5.2) (Laravel Components 5.5.*)'
}

因此$this->call($closure, $routeInfo[2])
獲得的就是上一節的'Lumen (5.5.2) (Laravel Components 5.5.*)'
而後把處理後獲得的數據傳進$this->prepareResponse()方法中組裝響應請求的數據
組裝完畢後,回到最初的run方法接着往下$response->send()
追蹤到SymfonyComponentHttpFoundationResponse這個類裏面(組裝響應數據也是這裏面)code

/**
     * Sends content for the current web response.
     *
     * @return $this
     */
    public function sendContent()
    {
        echo $this->content;

        return $this;
    }

    /**
     * Sends HTTP headers and content.
     *
     * @return $this
     */
    public function send()
    {
        $this->sendHeaders();
        $this->sendContent();

        if (function_exists('fastcgi_finish_request')) {
            fastcgi_finish_request();
        } elseif ('cli' !== PHP_SAPI) {
            static::closeOutputBuffers(0, true);
        }

        return $this;
    }

從這裏看出,那段'Lumen (5.5.2) (Laravel Components 5.5.*)'就是在這裏echo出來的

到此爲止,能夠大概知道了框架從請求到響應的基本流程其中還有一些中間件,事件監聽等知識後續學習補上,有什麼不對記得指出,互相學習~

相關文章
相關標籤/搜索