上篇:Laravel源碼入門-啓動引導過程(四)app/Http/Kernel.php
Kernel 做了兩件事,第一個是定義 $bootstraps[],做好了 boot 系統的準備,第二個是定義 各種 middleware,這些都對 $request 進行加工、處理、甄選、判斷,最終爲可以形成正確的、有效的 $response 做準備,都完成後,進行了 index.php 中的 $kernel->handle($request),返回 $response。
仔細分析發現,public/index.php 中 $kernel 在make() 時,真的只是做了準備,真正的載入環境變量(.env)、根據配置載入 Service Providers 等,實際在 $kernel->handle($request) 語句中進行。先貼出加入測試 echo 記錄下的載入過程結果。
// 開始 public/index.php
$app = require_once __DIR__.'/../bootstrap/app.php'
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
start-->$response = $kernel->handle()
// 進入 Illuminate/Foundation/Http/Kernel.php
Foundation/Http/Kernel::handle()
Foundation/Http/Kernel::sendRequestThroughRouter()
Foundation/Http/Kernel::bootstrap()
// 進入 Illumniate/Foundation/Application.php
Foundation/Application::bootstrapWith($bootstrapWith)
Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables
Illuminate\Foundation\Bootstrap\LoadConfiguration
reading config/app.php
Illuminate\Foundation\Bootstrap\HandleExceptions
Illuminate\Foundation\Bootstrap\RegisterFacades
Illuminate\Foundation\Bootstrap\RegisterProviders
Illuminate\Foundation\Bootstrap\BootProviders
// 回到 public/index.php
end<---$response = $kernel->handle()
下面具體看一下 Illuminate\Foundation\Http\Kernel.php 的 handle() 及相關代碼片段。
// Illuminate\Foundation\Http\Kernel.php 片段
/**
* The bootstrap classes for the application.
* 引導類,起引導作用的類
*
* @var array
*/
protected $bootstrappers = [
// 載入服務器環境變量(.env 文件)
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
// 載入配置信息(config 目錄)
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
// 配置如何處理異常
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
// 註冊 Facades
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
// 註冊 Providers
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
// 啓動 Providers
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
// 此處省略無關代碼
/**
* Handle an incoming HTTP request. 處理請求的 handle()
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function handle($request)
{
echo 'Foundation/Http/Kernel::handle() <br />';
try {
$request->enableHttpMethodParameterOverride();
// 將請求發送至中間件、路由處理。
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));
$response = $this->renderException($request, $e);
}
event(new Events\RequestHandled($request, $response));
return $response;
}
/**
* Send the given request through the middleware / router.
* 將請求發送至中間件、路由處理。
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
protected function sendRequestThroughRouter($request)
{
echo 'Foundation/Http/Kernel::sendRequestThroughRouter() <br />';
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
// Kernel 要啓動引導
$this->bootstrap();
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
/**
* Bootstrap the application for HTTP requests.
* 啓動引導(requests 驅動)
*
* @return void
*/
public function bootstrap()
{
echo 'Foundation/Http/Kernel::bootstrap() <br />';
if (! $this->app->hasBeenBootstrapped()) {
// 使用 Application 的 bootstrapWith()方法啓動引導
// 參數是 Kernel 中的 bootstrapers[]。
$this->app->bootstrapWith($this->bootstrappers());
}
}
=== 總結 ===
如先期描述的 handle() 通過 sendRequestThroughtRouter($request) 處理請求,返回 $response,途中進行了 啓動引導,$this->bootstrap(),進一步調用 Application 的 bootstrapWith(),將自己定義的 bootstrapper[] 傳入,這個 bootstrappers[] 如前定義,包括了載入服務器環境變量、配置信息、服務提供者、異常處理等。一切結束後,沒有拋出異常的話,返回 public/index.php,正如開始的 echo 記錄一樣。
附:Application 中 bootstrapWith() 代碼
下篇:Laravel源碼入門-啓動引導過程(六)LoadEnvironmentVariables
// Illuminate\Foundation\Application.php 代碼片段
/**
* Run the given array of bootstrap classes.
*
* @param array $bootstrappers
* @return void
*/
public function bootstrapWith(array $bootstrappers)
{
echo 'Foundation/Application::bootstrapWith($bootstrapWith) <br />';
$this->hasBeenBootstrapped = true;
foreach ($bootstrappers as $bootstrapper) {
echo $bootstrapper . '<br />';
$this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);
// 解析每個 $bootstrapper,由調用他們自身的 bootstrap(),引導。
$this->make($bootstrapper)->bootstrap($this);
$this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
}
}