Laravel源碼入門-啓動引導過程(七)LoadConfiguration

上篇:Laravel源碼入門-啓動引導過程(六)LoadEnvironmentVariables

上文介紹了 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;
    }
}

 

至此所有的配置信息導入完成。

下篇:Laravel源碼入門-啓動引導過程(八)HandleExceptions

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章