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

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

1.加載流程

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

2.何時加載配置?

內核啓動的時候。加載如下啓動類json

\Illuminate\Foundation\Http\Kernelbootstrap

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

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

3. 源碼分析

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

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

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已經加載到了
相關文章
相關標籤/搜索