IgnitionとCollisionで読み解くLaravelのエラー画面

概要

Laravel で開発していると、例外発生時に2種類の「エラー画面」に出会います。ブラウザに表示される詳細なエラーページと、php artisan やテスト実行時にターミナルへ出る整形済みのエラー表示です。

前者を描画しているのが Ignition、後者を担っているのが Collision です。どちらも Laravel に標準同梱されていますが、「どの経路でどちらが動くのか」「本番でなぜ出ないのか」を理解していないと、トラブルシュートで手が止まります。本記事でこの2つの役割分担と勘所を整理します。

環境

  • PHP 8.1 以降(Laravel 13 を使う場合は PHP 8.3 以降が必須。現行安定版は 8.5)
  • Laravel 9 / 10 / 11 / 12 / 13 系(spatie/laravel-ignition を前提。現行の標準同梱は 2.x 系)
  • nunomaduro/collision(composer create-project で require-dev に同梱。現行は 8.x 系)

Laravel 8 以前は Ignition が facade/ignition という別パッケージでした。なお、本記事が解説する「HTTP=Ignition / コンソール=Collision」の役割分担と bootstrap/app.php の withExceptions 方式は、Laravel 11 で導入されて以降、12 / 13 でも変わっていません。セキュリティの話にも関わるため、まずバージョンを確認します。

composer show spatie/laravel-ignition
composer show nunomaduro/collision

発生した問題

よくあるのは次の「見え方の食い違い」です。

  1. ローカルのブラウザでは詳細なスタックトレースが出るのに、本番にデプロイすると「500 Server Error」の素っ気ない画面しか出ない
  2. php artisan test ではきれいに色付きで出るのに、ログファイルは情報が少ない
  3. エラー画面に「解決策(Solution)」が出るときと出ないときがある

これらはバグではなく、Ignition と Collision の役割分担と動作条件を把握すれば説明がつきます。

原因

エラーの流れ

捕捉されなかった例外は最終的に App\Exceptions\Handler(Laravel 11 以降では bootstrap/app.php の withExceptions)に集約されます。そこから先の「表示」が実行コンテキストで分岐します。

  • HTTP リクエスト経由 → Ignition がレンダリング(APP_DEBUG=true のときだけ)
  • コンソール(artisan / テスト)経由 → Collision がレンダリング

同じ例外でも「ブラウザで見るかターミナルで見るか」で描画担当が変わります。

Ignition が本番で出ない理由

Ignition の詳細画面は config/app.php の debug(=APP_DEBUG)が true のときだけ有効です。

// config/app.php
'debug' => (bool) env('APP_DEBUG', false),

本番では APP_DEBUG=false にするのが鉄則なので、Ignition は無効化され、resources/views/errors/500.blade.php 等の汎用エラーページが表示されます。「本番で詳細が出ない」は正常な挙動です。逆に本番で Ignition の詳細画面が見えているなら、それは設定ミスであり即座に直すべき状態です。

Collision がコンソールを担当する理由

Collision は CollisionServiceProvider を通じて artisan とテストランナーに統合されます。require-dev に入っているため、本番の composer install --no-dev では読み込まれません。本番でコンソールエラーの見た目が素っ気ないのはこのためです。

対応方法

まず APP_DEBUG を確認する

php artisan tinker
>>> config('app.debug')
  • ローカルで詳細が出ない → .env が APP_DEBUG=false になっていないか、設定キャッシュが古くないか
  • 本番で詳細が出てしまう → ただちに APP_DEBUG=false にして設定キャッシュを張り直す
php artisan config:clear
php artisan config:cache

config:cache を実行すると .env の変更が反映されなくなります。.env を変えたら必ずキャッシュを張り直してください。

Ignition の挙動を絞り込む

設定ファイルを公開すると、挙動を細かく確認・制御できます。

php artisan vendor:publish --provider="Spatie\LaravelIgnition\IgnitionServiceProvider"

Solution(修正提案や実行可能アクション)は開発を速くしますが、本番では無効であるべきです。APP_DEBUG=false であれば Ignition 自体が動かないため、ここが担保の要になります。

実装例

HTTP とコンソールで表示が分岐することを、意図的に例外を投げて確認します。

// routes/web.php
Route::get('/boom', function () {
    throw new \RuntimeException('HTTP 経由の例外です');
});
// app/Console/Commands/BoomCommand.php
namespace App\Console\Commands;

use Illuminate\Console\Command;

class BoomCommand extends Command
{
    protected $signature = 'demo:boom';
    protected $description = 'コンソール経由で例外を投げる';

    public function handle(): int
    {
        throw new \RuntimeException('コンソール経由の例外です');
    }
}
  • /boom にブラウザでアクセス(APP_DEBUG=true)→ Ignition の詳細画面
  • php artisan demo:boom → Collision の整形出力

同じ RuntimeException でも描画担当が違うことが体感できます。例外ハンドラ側でのカスタマイズも可能です。

// Laravel 11 以降: bootstrap/app.php
->withExceptions(function (Illuminate\Foundation\Configuration\Exceptions $exceptions) {
    $exceptions->report(function (\Throwable $e) {
        // 独自ログ送信など
    });
})

確認方法

  1. .env を APP_DEBUG=true にして php artisan config:clear
  2. /boom にアクセスし、スタックトレース付きの Ignition 画面が出ることを確認
  3. .env を APP_DEBUG=false にして php artisan config:clear、再度 /boom で汎用 500 ページに変わることを確認
  4. php artisan demo:boom を実行し、Collision の整形出力を確認

この4ステップで「誰が・どの条件で描画しているか」が切り分けられます。

注意点

最大の注意点はセキュリティです。過去に Ignition(当時の facade/ignition)には、デバッグモードが有効な公開環境を狙った深刻な脆弱性(CVE-2021-3129、リモートコード実行につながるもの)が報告され、修正版がリリースされました。教訓はシンプルです。

  • 本番では APP_DEBUG=false を徹底する(Ignition の詳細画面・Solution 実行を露出させない)
  • Ignition / Laravel 本体を最新に保つ
  • デバッグツールを require-dev のまま本番へ混入させない(composer install --no-dev --optimize-autoloader)

便利なエラー画面は、裏を返せばアプリ内部を雄弁に語る画面でもあります。開発を速くする機能ほど、公開環境での露出に神経を使う必要があります。

まとめ

  • Laravel のエラー表示は HTTP=Ignition / コンソール=Collision で役割が分かれている
  • Ignition の詳細画面は APP_DEBUG=true のときだけ動く。本番で素っ気ないのは正常
  • Collision は require-dev 同梱で、artisan・テストの出力を整形する
  • トラブルシュートはまず APP_DEBUG と設定キャッシュの確認から
  • 過去の RCE 事例を踏まえ、本番でのデバッグモード無効化とバージョン更新を徹底する

「なぜこの画面が出ているのか」を説明できると、エラー対応の初動が一段速くなります。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。