Hiroto's diary

プログラミング関連とイベントの感想を書くかもしれない

Laravelの .env の値はconfig()経由で使う。

結論から言うと…

  • env()は コントローラー, モデル, etc.. 内で直接使わない。
  • config/*.phpenv()の値を入れてconfig()から参照する。

<?php
// config/my-app.php

return [
    // configに.envの内容を入れる。
    'my-env' => env('MY_ENV'),
];
<?php
// コントローラー内など

// config() を使用。
$my_env = config('my-app.my-env');

// これはダメなパターン。
$my_env = env('MY_ENV');

何故 env() を使ってはいけないのか

本番環境でconfig:cacheコマンドを実行した際、.envファイルを読み込まないから。コレに尽きます。

.envファイルはIlluminate\Foundation\Bootstrap\LoadEnvironmentVariablesクラスのbootstrap()で読み込まれるのですが、読み込む前にconfigのキャッシュの有無を確認し、キャッシュがあった場合は.envファイルを読み込まない仕様になっています。

当該部分のLaravelのコードを引用。

<?php
// 省略

    public function bootstrap(Application $app)
    {
        if ($app->configurationIsCached()) {
            return;
        }
        $this->checkForSpecificEnvironmentFile($app);
        try {
            (new Dotenv($app->environmentPath(), $app->environmentFile()))->load();
        } catch (InvalidPathException $e) {
            //
        } catch (InvalidFileException $e) {
            die('The environment file is invalid: '.$e->getMessage());
        }
    }

// 省略

github.com

大体の場合の本番環境では、高速化の為に設定を一纏めにするconfig:cacheコマンドを実行すると思うのですが、前述の通りキャッシュがあると.envが読み込まれないので、env()を直接叩いてると開発時やテスト時には動くけど本番環境で死ぬ。といった事になります。(実際なった)

実際に試す

適当なコントローラーを用意してddを使って値をダンプするだけ。

<?php
class HogeController extends Controller
{
    public function getHoge()
    {
        dd(
            env('MY_ENV'),
            config('my-app.my-env')
        );
    }
}

まずはキャッシュ無しでアクセス。

"Foo"

"Foo"

テスト環境や開発環境と同じ様にキャッシュを作成していないのでどちらも同じ値が取得できます。

次にキャッシュさせてアクセス。artisanconfig:cacheを実行してbootstrap/cache/config.phpを作成します。

php artisan config:cache

で、先ほどと同じ様にアクセスしてみる。

null

"Foo"

.envファイルが読み出されていないのでenv()で取得した所で値が入ってる訳もなくnullを返します。


と言う訳で最初に書いた通り、env()は直接使わずにconfig().envの値を入れて使いましょう

© 2015-2018 Hiroto-K