接着上篇$app->run();
--------------------分割线------------------------
$app是Application的实例,但是Application.php文件中找不到run方法
在类内部看到use ConcernsRoutesRequests,打开找到了run方法,
run方法注释写的是主要用于运行应用以及发送响应
/**
* 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方法
/**
* 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方法
/**
* 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();
}
}
里面就是处理路由对应的响应方式,并且组装响应数据准备返回
定义的路由是
$router->get('/', function () use ($router) {
return $router->app->version();
});
匹配到路由之后对应的处理是
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这个类里面(组装响应数据也是这里面)
/**
* 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出来的
到此为止,可以大概知道了框架从请求到响应的基本流程
其中还有一些中间件,事件监听等知识后续学习补上,有什么不对记得指出,互相学习~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。