昨天我們看過了 $this->runRoute($request, $this->findRoute($request));
這段裡面 findRoute()
的實作。
今天我們要來看看 runRoute()
的實作
/**
* Return the response for the given route.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Routing\Route $route
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function runRoute(Request $request, Route $route)
{
$request->setRouteResolver(fn () => $route);
$this->events->dispatch(new RouteMatched($route, $request));
return $this->prepareResponse($request,
$this->runRouteWithinStack($route, $request)
);
}
這裡面 runRouteWithinStack()
/**
* Run the given route within a Stack "onion" instance.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return mixed
*/
protected function runRouteWithinStack(Route $route, Request $request)
{
$shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
$this->container->make('middleware.disable') === true;
$middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);
return (new Pipeline($this->container))
->send($request)
->through($middleware)
->then(fn ($request) => $this->prepareResponse(
$request, $route->run()
));
}
到這邊,我們終於看到最核心執行路由的函數 $route->run()
被呼叫的地方了。
之後我們看 run()
的實作
/**
* Run the route action and return the response.
*
* @return mixed
*/
public function run()
{
$this->container = $this->container ?: new Container;
try {
if ($this->isControllerAction()) {
return $this->runController();
}
return $this->runCallable();
} catch (HttpResponseException $e) {
return $e->getResponse();
}
}
這邊會將輸入的路由區分成 Controller 定義的,或者是用 Callable 結構定義的,類似這種方式的路由
Route::get('/greeting', function () {
return 'Hello World';
});
今天我們要看的是 Controller 定義的,所以是看 $this->runController()
/**
* Run the route action and return the response.
*
* @return mixed
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*/
protected function runController()
{
return $this->controllerDispatcher()->dispatch(
$this, $this->getController(), $this->getControllerMethod()
);
}
這邊的 dispatch()
實作則是
/**
* Dispatch a request to a given controller and method.
*
* @param \Illuminate\Routing\Route $route
* @param mixed $controller
* @param string $method
* @return mixed
*/
public function dispatch(Route $route, $controller, $method)
{
$parameters = $this->resolveParameters($route, $controller, $method);
if (method_exists($controller, 'callAction')) {
return $controller->callAction($method, $parameters);
}
return $controller->{$method}(...array_values($parameters));
}
到這邊,我們終於看到 $controller->{$method}(...array_values($parameters))
這段執行 Controller Action 的部分了,這也就是這段程式透過這麼多類別,最後實際要做的事情:讓正確的控制器執行正確的方法。
今天這段程式就看到這邊,我們明天見