背景
写真投稿機能に新しいカラム(place_id)を追加する実装をした(下記は実際に紐付けられた場所名が表示されている画面)。
マイグレーション・モデル・コントローラーのバリデーションを修正した。
テスト(php artisan test、RefreshDatabaseで毎回マイグレーションし直す別DB)はすべてGreenだった。
しかし、実際にブラウザから操作すると「保存できない」という報告を受けた。テストが通っているのに実環境だけ動かない、という状況の切り分け手順をまとめる。
環境
- PHP 8.4 / Laravel
- Docker(
php-fpmベースのコンテナでopcache.enable=On,opcache.validate_timestamps=Off,opcache.enable_cli=Off)
原因1: 新しいmigrationが実DBに未適用だった
テストはRefreshDatabaseトレイトを使っており、テスト実行のたびにテスト専用DBに全マイグレーションを流し直す。
そのため、新しいマイグレーションファイルを作成しただけで満足してしまいがちになる。開発用の実DBに対するphp artisan migrateを忘れていても、テストではまったく気づけない。
docker exec <app_container> php artisan migrate:status
出力の該当行がPendingになっていれば未適用。php artisan migrateを実行して反映する。
原因2: opcacheでコード変更(コントローラー等)が反映されていなかった
migrationを適用してもまだ直らない場合に疑うべきなのがopcacheだ。
opcache.validate_timestamps=0(Off)にしていると、PHPはファイルの更新日時をチェックしなくなる。そのためopcache_reset()の呼び出しか、Webサーバー(php-fpmプロセス)の再起動をしない限り、修正後のコードが反映されない(公式ドキュメント)。
docker restart <app_container>
見分け方
opcache.enable_cli=Offにしている場合、CLIコマンド(php artisan route:list等)はopcacheの影響を受けないため常に最新のコードで動く。
「CLIで確認すると正しいのに、実際のHTTPリクエストだけ古い挙動のまま」という食い違いが出たら、opcacheが原因である典型的なサインになる。
まとめ
- テストがGreenでも実DB・実環境側の反映漏れは検知できない。バックエンド変更後の動作確認では、症状を問わずまず
migrate:statusを確認する -
opcache.validate_timestamps=Offな環境では、コード修正後にコンテナ(php-fpmプロセス)を再起動する習慣をセットにする - 「migrate」→「restart」の2点セットをチェックリスト化しておくと切り分けが早い