Laravelのenvの設定処理はどうなっているのか
途中までしか書けてませんが、必要なことは書いてるので一旦公開します。
面倒な人向けのまとめ
- キャッシュされた設定があるならそれが優先的にロードされ、以降の処理はされない。
- APP_ENV環境変数があるかを確認する
-
.env
ファイル(APP_ENV環境変数があって該当ファイルが存在する場合は.env.環境名
ファイル)を読み込む
注意点
- 環境変数の値のほうが優先です。(
$_ENV
で、すでにロードされている) - 勘違いされがちですが、
.env.環境名
と.env
両方が読み込まれると言ったことはありません。 -
config:cache
でキャッシュすると.env
をロードしなくなるのでenv関数をconfig以外で使うのはNG。
実際のコードを見ていく
まず、EnvをロードしようとするのはKernel.php
のbootstrappers
にあるLoadEnvironmentVariables
です。
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,
];
LoadEnvironmentVariablesの処理
public function bootstrap(Application $app)
{
if ($app->configurationIsCached()) {
return;
}
$this->checkForSpecificEnvironmentFile($app);
try {
$this->createDotenv($app)->safeLoad();
} catch (InvalidFileException $e) {
$this->writeErrorAndDie($e);
}
}
$app->configurationIsCached()
cache/config.php
の中身があるかをチェックします。
これはphp artisan config:cache
を利用した場合に設定類をキャッシュするのでこのキャッシュファイルがある場合はこのLoadEnvironmentVariables
の処理はされません。
$this->checkForSpecificEnvironmentFile($app)
対象の処理は以下です。
protected function checkForSpecificEnvironmentFile($app)
{
if ($app->runningInConsole() &&
($input = new ArgvInput)->hasParameterOption('--env') &&
$this->setEnvironmentFilePath($app, $app->environmentFile().'.'.$input->getParameterOption('--env'))) {
return;
}
$environment = Env::get('APP_ENV');
if (! $environment) {
return;
}
$this->setEnvironmentFilePath(
$app, $app->environmentFile().'.'.$environment
);
}
この処理を見てみると、アプリケーションの環境情報を取得できた場合に$this->setEnvironmentFilePath
でenvファイルの名前を登録しています。
Env::get('APP_ENV')
が一番悩ましい部分ですが、ここではまだ.envファイルのロードはされていないので環境変数としてAPP_ENV
が定義されている場合にのみ存在するということになります。
一番わかりやすい例としてはテストで、phpunit.xmlに記述する<env name="APP_ENV" value="testing" force="true"/>
とか、テスト用DBにマイグレーションを実施するためにphp artisan migrate --env=testing
とかがここに引っかかることになります。
ここでは環境名をくっつけるようにしているので、APP_ENV
がtesting
だと、.env.testing
をロードする予定のファイル名としているわけです。
なお、setEnvironmentFilePathの処理に該当ファイルが存在しているかのチェックがあるので、該当ファイルがない場合は.env
が読まれることになります。
$this->createDotenv($app)->safeLoad()
protected function createDotenv($app)
{
return Dotenv::create(
Env::getRepository(),
$app->environmentPath(),
$app->environmentFile()
);
}
理解に悩むのがEnv::getRepository()
です。
ちょっとこの辺り複雑な感じだったので、後ほど頑張って書こうと思います。。。
Discussion