上文介绍了 LoadEnvironmentVariables,载入 .env 环境配置,在 《Laravel源码入门-启动引导过程(五)$kernel->handle($request)》中第二个要载入的是 LoadConfiguration,也就是 Foundation\Http\Kernel::bootstrapers[] 的第二个
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class, 如下:
// 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,
];
我们再直接贴出 LoadConfiguration 类的代码,进行分析,非常直观,如下:
<?php
namespace Illuminate\Foundation\Bootstrap;
use Exception;
use SplFileInfo;
use Illuminate\Config\Repository;
use Symfony\Component\Finder\Finder;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Config\Repository as RepositoryContract;
class LoadConfiguration
{
/**
* Bootstrap the given application.
* 引导注入的$app
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function bootstrap(Application $app)
{
$items = [];
// First we will see if we have a cache configuration file. If we do, we'll load
// the configuration items from that file so that it is very quick. Otherwise
// we will need to spin through every configuration file and load them all.
// 首先看看缓存路径存在否,如果不存在,循环 config/目录中的所有 .php 文件。
if (file_exists($cached = $app->getCachedConfigPath())) {
$items = require $cached;
$loadedFromCache = true;
}
// Next we will spin through all of the configuration files in the configuration
// directory and load each one into the repository. This will make all of the
// options available to the developer for use in various parts of this app.
// 循环之前,实例化一个 $config 仓库对象,注册到到 $app 上,共享。
$app->instance('config', $config = new Repository($items));
if (! isset($loadedFromCache)) {
// 将 config 目录下的 所有 .php 配置信息 载入到 $config 中
$this->loadConfigurationFiles($app, $config);
}
// Finally, we will set the application's environment based on the configuration
// values that were loaded. We will pass a callback which will be used to get
// the environment in a web context where an "--env" switch is not present.
// 不懂这句。。。
$app->detectEnvironment(function () use ($config) {
return $config->get('app.env', 'production');
});
// 设置时区,下面注释语句应该一样
// date_default_timezone_set($config->get('app.timezone'));
date_default_timezone_set($config->get('app.timezone', 'UTC'));
// 设置内部字符编码
mb_internal_encoding('UTF-8');
}
/**
* Load the configuration items from all of the files.
* 从所有的 config/ 下的 .php 中 载入配置信息
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @param \Illuminate\Contracts\Config\Repository $repository
* @return void
*/
protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
{
// 找到所有 .php 文件,尽管有子目录
// 根据下面 getConfigurationFiles() 得到了所有文件的 $key=>$path 对
// 比如:
/*
"app" => "/Users/me/mydev/laravel_orig/config/app.php"
"auth" => "/Users/me/mydev/laravel_orig/config/auth.php"
"broadcasting" => "/Users/me/mydev/laravel_orig/config/broadcasting.php"
"cache" => "/Users/me/mydev/laravel_orig/config/cache.php"
"config_test.config_test" => "/Users/me/mydev/laravel_orig/config/config_test/config_test.php"
"config_test.config_test_2.config_test2" => "/Users/me/mydev/laravel_orig/config/config_test/config_test_2/config_test2.php"
"database" => "/Users/me/mydev/laravel_orig/config/database.php"
"filesystems" => "/Users/me/mydev/laravel_orig/config/filesystems.php"
"mail" => "/Users/me/mydev/laravel_orig/config/mail.php"
"queue" => "/Users/me/mydev/laravel_orig/config/queue.php"
"services" => "/Users/me/mydev/laravel_orig/config/services.php"
"session" => "/Users/me/mydev/laravel_orig/config/session.php"
"view" => "/Users/me/mydev/laravel_orig/config/view.php"
*/
$files = $this->getConfigurationFiles($app);
if (! isset($files['app'])) {
throw new Exception('Unable to load the "app" configuration file.');
}
foreach ($files as $key => $path) {
$repository->set($key, require $path);
}
}
/**
* Get all of the configuration files for the application.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return array
*/
protected function getConfigurationFiles(Application $app)
{
$files = [];
$configPath = realpath($app->configPath());
foreach (Finder::create()->files()->name('*.php')->in($configPath) as $file) {
$directory = $this->getNestedDirectory($file, $configPath);
$files[$directory.basename($file->getRealPath(), '.php')] = $file->getRealPath();
}
return $files;
}
/**
* Get the configuration file nesting path.
*
* @param \SplFileInfo $file
* @param string $configPath
* @return string
*/
protected function getNestedDirectory(SplFileInfo $file, $configPath)
{
$directory = $file->getPath();
if ($nested = trim(str_replace($configPath, '', $directory), DIRECTORY_SEPARATOR)) {
$nested = str_replace(DIRECTORY_SEPARATOR, '.', $nested).'.';
}
return $nested;
}
}
至此所有的配置信息导入完成。