LoginSignup
21
13

More than 3 years have passed since last update.

[Laravel]環境変数、サーバーから見るか?ファイルから見るか?

Posted at

Laravelをお使いのみなさんは.envで環境変数を設定しているかと思いますが、もちろんサーバーの環境変数や実行時にコマンドで環境変数を指定することも可能です。

さて、.envとサーバー環境変数で同じキーを指定した場合にLaravelはどちらの値を優先するか、という記事です。

Laravelでの環境変数

Laravelではphpdotenvというライブラリを利用して環境変数を取得しています。
https://github.com/vlucas/phpdotenv

以下で各種Adapterが登録されます。
※Laravel v7系
※phpdotenv v4系

Illuminate\Support\Env
public static function getRepository()
{
    if (static::$repository === null) {
        $adapters = array_merge(
            [new EnvConstAdapter, new ServerConstAdapter],
            static::$putenv ? [new PutenvAdapter] : []
        );

        static::$repository = RepositoryBuilder::create()
            ->withReaders($adapters)
            ->withWriters($adapters)
            ->immutable()
            ->make();
    }

    return static::$repository;
}

ここでEnvConstAdapter,ServerConstAdapter,PutenvAdapterの順に登録しています。

Adapter

先程登録されていた各種Adapterは以下のような仕組みになっています。

EnvConstAdapter

PHPのスーパーグローバル変数$_ENVから値の取得・登録をします。
$_ENVは現在のスクリプトに渡された環境変数を取得します。

ServerConstAdapter

PHPのスーパーグローバル変数$_SERVERから値の取得・登録をします。
$_SERVERはサーバーに定義された環境変数を取得します。

PutenvAdapter

PHPの組み込み関数getenvputenvを利用して値の取得・登録をします。

環境変数の取得

env('string')が呼び出される先は以下のように先程登録したAdapterを順に参照して、定義されている場合に値を返します。
定義がなければnullが返されます。

Dotenv\Repository\AdapterRepository
protected function getInternal($name)
{
    foreach ($this->readers as $reader) {
        $result = $reader->get($name);
        if ($result->isDefined()) {
            return $result->get();
        }
    }

    return null;
}

結局優先順位はどうなってるの?

.envファイルが登録される際の挙動を見るとわかります。

Dotenv\Repository\AbstractRepository
public function set($name, $value = null)
{
    if (!is_string($name)) {
        throw new InvalidArgumentException('Expected name to be a string.');
    }

    // Don't overwrite existing environment variables if we're immutable
    // Ruby's dotenv does this with `ENV[key] ||= value`.
    if ($this->immutable && $this->get($name) !== null && $this->loaded->get($name)->isEmpty()) {
        return;
    }

    $this->setInternal($name, $value);
    $this->loaded->set($name, '');
}

ここのガート節で

if ($this->immutable && $this->get($name) !== null && $this->loaded->get($name)->isEmpty()) {
    return;
}

とありますね。
つまり、EnvConstAdapter,ServerConstAdapter,PutenvAdapterのどれらにも未定義の場合は値を新たに追加しています。

なので優先される値は

  1. 実行時の環境変数
  2. サーバー環境変数
  3. .envファイルの変数

になるかと思います。(違ったらご指摘ください)

21
13
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
21
13