1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

laravel configを読み込む仕組み

Posted at

laravel 7.5.2でconfigが読み込まれる仕組みを追う。

index.phpでkernelのhendle関数が実行され、内部でbootstrap処理が実行されます。
bootstrap処理では、Illuminate\Foundation\Http\Kernel.phpのbootstrappersプロパティで指定しているクラスを順次実行し、Applicationの起動処理を行います。
ここの LoadConfiguration::classでconfigに関連する処理を行ってそうです。

Illuminate\Foundation\Http\Kernel.php
    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,
    ];

LoadConfiguration.php

bootstrap処理では、bootstrapとして指定されたクラスのbootstrap関数が実行されます。
LoadConfiguration.phpのbootstrap関数はこちらです。

LoadConfiguration.php
    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.
        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.
        $app->instance('config', $config = new Repository($items));

        if (! isset($loadedFromCache)) {
            $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', 'UTC'));

        mb_internal_encoding('UTF-8');
    }

まず、configのキャッシュファイルパスがあるかを調べます。ある場合はそれを使います。

LoadConfiguration.php
        if (file_exists($cached = $app->getCachedConfigPath())) {
            $items = require $cached;

            $loadedFromCache = true;
        }

続いて、サービスコンテナにconfigを登録します。instanceはRepository.phpになります。

LoadConfiguration.php
$app->instance('config', $config = new Repository($items));

もしキャッシュからの読み込みでなかったらconfig情報を読み込みに行きます。

        if (! isset($loadedFromCache)) {
            $this->loadConfigurationFiles($app, $config);
        }

loadConfigurationFiles関数を見てみましょう。
内部ではgetConfigurationFiles関数でfile連想配列を取得し、$repositoryにsetしています。
getConfigurationFiles関数では、configPathに存在する全phpファイルパスを加工して取得し、
key = ディレクトリを.で繋いだファイルパス(config/hoge/fuga.phpならhoge.fuga.piyo)
value = configファイルの絶対パス
にしたfiles連想配列を返しています。
そして$repository->set($key, require $path);
key = ディレクトリを.で繋いだファイルパス
value = config読み込んだもの
で値をセットしています。
これでbootstrap処理は終わりです。

    protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
    {
        $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);
        }
    }
    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();
        }

        ksort($files, SORT_NATURAL);

        return $files;
    }
    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;
    }

configヘルパー関数

次はconfigヘルパー関数の動きを見ていきましょう。
configヘルパー関数は Illuminate/Foundation/helpers.php で定義されています。
helpersはautoloadによって読み込まれます(たぶん?)

configヘルパー関数では単純にサービスコンテナを使ってconfigインスタンス = Repositoryインスタンスを取得し、get関数を実行しています。
(keyがarrayだとsetになるの怖すぎ...)

helpers.php
if (! function_exists('config')) {
    /**
     * Get / set the specified configuration value.
     *
     * If an array is passed as the key, we will assume you want to set an array of values.
     *
     * @param  array|string|null  $key
     * @param  mixed  $default
     * @return mixed|\Illuminate\Config\Repository
     */
    function config($key = null, $default = null)
    {
        if (is_null($key)) {
            return app('config');
        }

        if (is_array($key)) {
            return app('config')->set($key);
        }

        return app('config')->get($key, $default);
    }
}

ではRepositoryのget関数を見てみましょう。先ほどsetしたitemsに指定したkeyにマッチするにvalueを返しています。
なるほど。

Repository.php
    public function get($key, $default = null)
    {
        if (is_array($key)) {
            return $this->getMany($key);
        }

        return Arr::get($this->items, $key, $default);
    }

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?