Laravel 加载之 bootstrap
简介
此章,主要讲的内容是 $this->bootstrap(); ,Laravel 中的配置错误处理、配置日志记录、 检测应用环境 以及执行其他需要完成的任务 。
bootstrap 引导其实质是将下面的类中的 bootstrap 方法都执行一遍
protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];
看一下 handle 方法
public function handle($request)
{
    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);
    }
    $this->app['events']->dispatch(
        new Events\RequestHandled($request, $response)
    );
    return $response;
}
代码中标注的重点的一行 $response = $this->sendRequestThroughRouter($request); 就是这个 handle 方法核心内容了。
我们继续看 sendRequestThroughRouter 方法
protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);
    Facade::clearResolvedInstance('request');
    $this->bootstrap();  // 这就是这一章要讲的东西了
    return (new Pipeline($this->app))
        ->send($request)
        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
        ->then($this->dispatchToRouter());
}
代码中标注的 $this->bootstrap(); 就是 Laravel 引导配置加载的开始了,具体干了哪些工作呢:
- 加载 
.env文件,将配置加载到内存中 - 加载 
config目录下的所有配置文件 - 修改系统默认异常处理函数(如语法错误等),将其替代为 
Laravel的异常处理。这就是为什么在开发Laravel应用时,语法出现错误,而报错信息已一种非常好看的界面显示的缘故 - 注册 
Facades,将Laravel内的Facades类中的静态属性$app赋值为 服务容器 - 注册服务提供者,区分即时实例化和延时实例化,即时的不需要标识别名,而延时的需要标识别名,主要对 
config/app.php中providers键对应值(服务器提供者类全名)进行分类 - 执行服务提供者的 
boot方法,其中路由文件加载和读取,就是在此步骤进行的 
下面我们看一下 $this->bootstrap();
public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
        $this->app->bootstrapWith($this->bootstrappers());
    }
}
这段代码是指,有没有进行过引导呀,有的话,不进入引导程序,没有则进入
下面我们看一下进入引导的,先看 $this->bootstrappers()
protected function bootstrappers()
{
    return $this->bootstrappers;
}
这段就是返回了 bootstrappers 属性,它就是前言中展示的数组
下面我们看一下容器方法 bootstrapWith
public function bootstrapWith(array $bootstrappers)
{
    $this->hasBeenBootstrapped = true;
    foreach ($bootstrappers as $bootstrapper) {
        $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);
        $this->make($bootstrapper)->bootstrap($this);  // 核心在这
        $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
    }
}
上面核心代码,就是遍历 $bootstrapper 数组,将里面的类实例化后,执行实例化后的 bootstrap 方法,将容器作为参数传入。
这一章,讲到这里,下一章我们看一下 $bootstrappers 数组的第一个值(类全名)的引导(即加载 .env)
protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,  // 下一章看这个哦
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];