深入理解 Laravel 中 config 配置加載原理


Laravel的配置加載其實就是加載config目錄下所有文件配置。如何過使用php artisan config:cache則會把加載的配置合並到一個配置文件中,下次請求就不會再去加載config目錄。

1.加載流程

  1. LoadEnvironmentVariables .env環境配置加載。如果緩存配置是不會加載.env
  2. LoadConfiguration 判斷是否緩存配置
  3. 是,則直接加載配置,不會加載config目錄所有文件了
  4. 否,則加載config目錄所有PHP文件

2.什么時候加載配置?

內核啟動的時候。加載以下啟動類

\Illuminate\Foundation\Http\Kernel

protected $bootstrappers = [
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,  // 加載 .env
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, // 加載config配置
        ...
    ];

本文重點講解第二個config配置加載。第一個請查看 深入理解 Laravel 中.env 文件讀取

3. 源碼分析

LoadConfiguration類中config配置加載的具體邏輯。

其實就是判斷緩存是否存在,存在則加載,不存在則遞歸遍歷config目錄所有php文件。如果運行php artisan config:cache,則會把加載結果保存在bootstrap/cache目錄中;你可能還會看到services.php文件,這是一個保存所有的服務提供者的文件,具體以后會講。

public function bootstrap(Application $app)
    {
        $items = [];

       // 首先,我們將看看是否有緩存配置文件。 如果是,我們將從該文件加載配置項,因此它非常快。 
       // 否則,我們需要遍歷每個配置文件並加載它們。
        if (file_exists($cached = $app->getCachedConfigPath())) {
            // 加載緩存的配置文件
            $items = require $cached;

            $loadedFromCache = true;
        }

        // 接下來,我們將遍歷配置目錄中的所有配置文件,並將每個配置文件加載到Repository中。
        // 這將使開發人員可以使用所有選項,以便在此應用程序的各個部分中使用。
        $app->instance('config', $config = new Repository($items));

        // 如果沒有緩存配置才會去加載config目錄
        if (! isset($loadedFromCache)) {
            // 加載config目錄所有PHP文件
            $this->loadConfigurationFiles($app, $config);
        }

        //最后,我們將根據加載的配置值設置應用程序的環境。 
        // 我們將傳遞一個回調,該回調將用於在Web環境中獲取環境,其中不存在“--env”開關。
        $app->detectEnvironment(function () use ($config) {
            return $config->get('app.env', 'production');
        });

        // 設置時區
        date_default_timezone_set($config->get('app.timezone', 'UTC'));

        mb_internal_encoding('UTF-8');
    }

    /**
     * 從所有文件加載配置項。因此效率很低
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @param  \Illuminate\Contracts\Config\Repository  $repository
     * @return void
     * @throws \Exception
     */
    protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
    {
        // 遍歷出所有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);
        }
    }

4.小結與注意點

  1. php artisan config:cache之后不會加載config配置,即便你修改了config目錄中的配置文件也是不生效的,除非清除緩存php artisna config:clear,或者重新緩存 php artisan config:cache
  2. 因為配置緩存可以提高效率,因此推薦生產環境使用配置緩存。
  3. 不能在config目錄內定義配置以外的東西。比如在config目錄內定義類,定義常量,自定義函數。這些都是不推薦的,因為配置緩存之后,config目錄任何文件都不會加載,這些類或者常量不存在,最終導致自動加載失敗。解決方案是使用composer.json的自動加載配置來加載:
"autoload": {
        "classmap": [
            "database/seeds",
            "database/factories"
        ],
        "psr-4": {
            "App\\": "app/"
        },
        "files": [
            # 這樣那個會加載helpers.php文件了。該文件定義的是輔助函數
            "bootstrap/helpers.php"
        ]
    },
  1. 在 config 中調用其他的 config('something.item') 是不會預期的加載的。因為不能保證配置something.item已經加載到了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM