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