Masayan tech blog.

  1. ブログ記事一覧>
  2. 【Laravel8】開発環境で安易にconfigファイルのキャッシュを作成してはいけない話

【Laravel8】開発環境で安易にconfigファイルのキャッシュを作成してはいけない話

公開日

開発環境でphp artisan config:cacheを安易に実行すべきではない

configファイルがロードされる仕組みをきちんと理解していないとやってしまいがちな下記コマンドについてです。

php artisan config:cache

公式ドキュメントでも以下のように言及されています。
※本番環境ではパフォーマンス向上のためにphp artisan config:cacheをするべきだとしています。

一般的には、本番環境へのデプロイ作業の一環として、php artisan config:cacheコマンドを実行すべきでしょう。アプリケーションの開発期間中は設定が頻繁に変更されることも多いので、ローカルでの開発中にこのコマンドを実行してはいけません。

理由 

php artisan config:cacheを実行すると、それ以降(キャッシュを消去しない限り)configディレクトリ配下の設定ファイルを修正するたびにphp artisan config:cacheを実行しなければ設定が反映されなくなってしまい、開発を行う上で非常に煩雑になるためです。

これは、一度設定ファイルをキャッシュするとキャッシュされた設定ファイルを優先的に読みにいくという仕組み上、configディレクトリ配下の設定ファイルが読み込まれないために発生します。

キャッシュの有無による流れの違い

ブラウザからリクエストを受けた際の起点となるindex.phpでkernelのhendle関数が実行され、内部でbootstrap処理が実行されます。

※Laravelのライフサイクルについてはこちらの記事を参照ください。

【重要】Laravelのライフサイクルをざっくりと解説してみる

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

/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php

protected $bootstrappers = [
  \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
〜省略〜
];

bootstrap処理では、bootstrapとして指定されたクラスのbootstrap関数が実行されます。
LoadConfiguration.phpのbootstrap関数は以下の通りですが、キャッシュがある場合とない場合で処理が異なってきますので、それぞれ記載します。

/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php

class LoadConfiguration
{
  public function bootstrap(Application $app)
  {
    $items = [];
    if (is_file($cached = $app->getCachedConfigPath())) {
    $items = require $cached;

    $loadedFromCache = true;
    }
    $app->instance('config', $config = new Repository($items));

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

  }
}

キャッシュがある(bootsrap/cache/config.phpが存在する)場合

bootstrap/cache/config.phpが返す配列を読み込む

まずif (file_exists($cached = $app->getCachedConfigPath()))でキャッシュされたファイルがあるかどうか確認します。
$app->getCachedConfigPath()は特に設定を変更していない場合{your-project-path}/bootstrap/cache/config.phpという文字列が返されます。

php artisan config:cacheを打つとbootstrap/cache配下にconfig.phpが生成されます(キャッシュされた設定ファイル)が、このconfig.phpは全設定をArrayで返します。このファイルをrequireして$items変数に代入し、$item変数を元にRepositoryクラス(/Illuminate/Config/Repository.php)をnewしてサービスコンテナに登録します。これがキャッシュがある場合の読み込みです。

キャッシュがない(bootsrap/cache/config.phpが存在しない)場合

configディレクトリ配下の各phpファイルから配列を読み込む

if (file_exists($cached = $app->getCachedConfigPath()))がfalse、つまりキャッシュ用の設定ファイルが見つからない場合は$itemsは空のままRepositoryクラスがnewされたあとに、$this->loadConfigurationFiles()が呼び出され実行されることによって設定値が読み込まれます。

このメソッドの内部ではconfigディレクトリ配下のファイル(キャッシュではなく、元になる設定ファイル)からkeyとvalueを取り出し、repositoryインスタンス(先ほどnewしたRepositoryクラスのインスタンス)のsetメソッドによって設定値を一つづつ読み込んでいます。

/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php

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);
  }
}

キャッシュを削除

なお、以下コマンドを実行するとキャッシュ(bootsrap/cache/config.php)を削除できます。

php artisan config:clear

まとめ

いかがでしたでしょうか。本記事では、【Laravel8】開発環境で安易にconfigファイルのキャッシュを作成してはいけないというテーマで説明を行なっています。php artisan config:cacheを実行すると、キャッシュを消去しない限りconfigディレクトリ配下の設定ファイルを修正するたびにphp artisan config:cacheを実行しなければ設定が反映されなくなってしまい、開発を行う上で非常に煩雑になるためです。