Laravelのデバッグテクニック:効率的なバグ修正とトラブルシュートの実務手順
- 作成日 2026.02.10
- その他
Laravelの不具合対応は「原因の切り分けが速いかどうか」で作業時間が決まる。闇雲にログを増やすより、再現条件の固定→観測ポイントの設置→原因の絞り込み→恒久対策(テスト・監視)までを手順化すると、同じ種類の障害を短時間で処理できる。この記事は、Laravel標準機能(ログ、例外、tinker、HTTPテスト、キュー、DB観測)と周辺ツール(Xdebug、Telescopeなど)を、実務の流れに沿ってまとめる。
- 1. 最初に固定する:再現条件(いつ・誰が・何をしたら起きるか)
- 2. 切り分けの順番:アプリ・設定・依存・インフラのどこが壊れているか
- 3. ログ設計:原因を出すログと、後で追えるログを分ける
- 4. 例外の見方:stack traceの「最初に自分のコードが出る場所」を見る
- 5. dump/ddの使い所:本番はやらない、ステージングで最短に切る
- 6. tinkerでの再現:DBの現状をその場で検証して仮説を潰す
- 7. SQL観測:クエリログとN+1の検出で“遅い原因”を特定する
- 8. Eloquentの落とし穴:null・型・スコープ・withの有無を疑う
- 9. HTTPデバッグ:リクエスト/レスポンスを固定して“同じ条件”で叩く
- 10. テストで再現して“恒久化”:バグはテストにしてから直す
- 11. キューのデバッグ:失敗ジョブ、リトライ、冪等性の確認
- 12. キャッシュ/設定の罠:反映されない問題はcacheクリアの筋道で潰す
- 13. 本番トラブルの基本:観測を増やし、影響を止め、原因を追う
- 14. デバッグツールの使い分け:Telescope / Xdebug / プロファイラ
- 15. まとめ:Laravelデバッグを速くするチェックリスト
最初に固定する:再現条件(いつ・誰が・何をしたら起きるか)
トラブルシュートが長引く原因の多くは「再現条件が曖昧」なこと。まずは次を紙に書ける状態にする。
・発生環境:local / staging / production
・発生頻度:常に / ときどき / 特定条件のみ
・入力:URL、パラメータ、ヘッダ、ログイン状態、権限
・期待結果と実結果:画面、APIレスポンス、DBの差分
・直前に入った変更:デプロイ日時、マイグレーション、設定変更
再現できない場合は「ログに残っている事実」から観測を増やし、再現条件を詰める。
切り分けの順番:アプリ・設定・依存・インフラのどこが壊れているか
最短で原因に近づく順番の例。
1) ルーティング/認証(入口で落ちていないか)
2) バリデーション/リクエスト整形(入力が想定通りか)
3) DB/トランザクション(クエリが壊れていないか)
4) 外部API(タイムアウト、認証、レート制限)
5) キュー/非同期(ジョブが落ちていないか)
6) キャッシュ/セッション(古い値が残っていないか)
7) 環境差(.env、PHP拡張、Node、権限、時刻)
最初から全部疑うと遅い。入口から順に潰すのが速い。
ログ設計:原因を出すログと、後で追えるログを分ける
ログは「今の原因究明」と「次回からの再発防止」で目的が違う。
・原因究明用:入力/分岐/外部API応答/例外を短期間だけ増やす
・運用ログ:リクエストID、ユーザーID、重要な状態遷移だけを恒常的に残す
重要なのは“関連付け”。同じリクエスト内のログが追えるようにリクエストIDを付ける。
// 例:コントローラ内で最低限の観測
logger()->info('profile.update:start', [
'user_id' => auth()->id(),
'payload_keys' => array_keys(request()->all()),
]);例外の見方:stack traceの「最初に自分のコードが出る場所」を見る
スタックトレースは上から読むより、フレームを辿って「vendorではなく自分のコードが最初に出る行」を探すと速い。
・どの入力で例外が起きたか(Request)
・どのクエリ/外部呼び出しの直後か
・nullが混ざったのか、型がズレたのか、権限が足りないのか
例外メッセージは“結果”で、原因はその直前の入力・状態にあることが多い。
dump/ddの使い所:本番はやらない、ステージングで最短に切る
dd() は強力だが、本番で止めると事故になる。
・local/stagingで再現できるなら dd は最速
・本番はログ/メトリクスで観測し、停止系は避ける
また dump は“必要なキーだけ”に絞ると読みやすい。
// 例:巨大なモデルを全部dumpしない
dump([
'id' => $user->id,
'email' => $user->email,
'status' => $user->status,
]);tinkerでの再現:DBの現状をその場で検証して仮説を潰す
エラーの多くは「想定していないデータ」が原因。tinkerで状態を確認すると手戻りが減る。
php artisan tinker
// 例:対象ユーザーの状態確認
$user = \App\Models\User::find(123);
$user->toArray();SQL観測:クエリログとN+1の検出で“遅い原因”を特定する
遅い/落ちる問題はSQLが原因のことが多い。
・N+1:ループ内でクエリが増えている
・不要なselect *:転送量が増える
・インデックス不在:特定条件で急に遅くなる
開発環境でクエリを観測し、どのSQLが増えているかを固定する。
// 例:SQLを一時的に観測(開発向け)
\DB::listen(function ($query) {
logger()->debug('sql', [
'sql' => $query->sql,
'bindings' => $query->bindings,
'time_ms' => $query->time,
]);
});Eloquentの落とし穴:null・型・スコープ・withの有無を疑う
よくある原因の型。
・find() がnullを返しているのに ->xxx して落ちる
・whereIn に空配列が入り、意図しない結果になる
・スコープが効きすぎて対象が消える(グローバルスコープ)
・with() が無くてN+1、with() が多すぎて重い
・casts が想定と違い、比較演算がズレる
// 例:null対策(404へ)
$post = \App\Models\Post::findOrFail($id);HTTPデバッグ:リクエスト/レスポンスを固定して“同じ条件”で叩く
再現性を上げるには「同じ入力で叩ける」ことが重要。
・curlで同じリクエストを作る
・ヘッダ(認証、Content-Type)も固定
・JSONの形を固定
・APIレスポンスの差分を比較
curl -X POST "https://example.com/api/posts" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"title":"Hello","body":"Body"}'テストで再現して“恒久化”:バグはテストにしてから直す
再発防止の最短は「落ちた条件をテストにする」こと。修正前にテストをRedにし、修正でGreenに戻すと“同じバグが戻らない”状態になる。
// tests/Feature/PostCreateTest.php(例:不正入力で422になるべき)
public function test_title_is_required(): void
{
$user = \App\Models\User::factory()->create();
$res = $this->actingAs($user)
->postJson('/api/posts', ['body' => 'x']);
$res->assertStatus(422);
}キューのデバッグ:失敗ジョブ、リトライ、冪等性の確認
「画面は成功したのに裏で失敗していた」系はキューで起きやすい。
・failed_jobs を見る
・例外内容と入力payloadを確認
・リトライで二重実行しても壊れない(冪等性)
・外部APIはタイムアウト/リトライ方針を固定
キューは“成功/失敗の観測”が弱いと気づくのが遅れるので、失敗通知は必須。
キャッシュ/設定の罠:反映されない問題はcacheクリアの筋道で潰す
発生しやすい状況:
・.env変更後に挙動が変わらない(config cacheが残っている)
・ルート更新したのに404/挙動が古い(route cache)
・ビュー更新が反映されない(view cache)
・権限やロールが変なのに直らない(アプリ側キャッシュ)
キャッシュを消すと直る場合は「どのキャッシュが原因か」を特定して、デプロイ手順に組み込む。
php artisan optimize:clear
# 必要に応じて
php artisan config:clear
php artisan route:clear
php artisan view:clear本番トラブルの基本:観測を増やし、影響を止め、原因を追う
本番は「直す」より「止血」が優先になることがある。
・機能フラグで一時停止(外部API連携、重い集計など)
・レート制限/タイムアウトを短くして詰まりを減らす
・エラーレスポンスを安全にする(500連発を避ける)
・ログに最低限の入力と例外を残す
止血後に再現条件を作り、テスト化してから恒久対応へ進めると戻りが少ない。
デバッグツールの使い分け:Telescope / Xdebug / プロファイラ
・Telescope:リクエスト、クエリ、例外、ジョブなどの流れを把握しやすい(開発/検証向け)
・Xdebug:ブレークポイントで変数の変化を追う(ローカルの最強手段)
・プロファイラ:遅い箇所を数値で特定(SQL、外部API、レンダリング)
ツールは“使う場面”が違うので、目的に合わせて切り替えるのが効率的。
まとめ:Laravelデバッグを速くするチェックリスト
・再現条件(環境/入力/頻度/期待と実結果)を固定
・入口→DB→外部→非同期の順で切り分け
・ログは関連付け(リクエストID)と最小観測で追える形にする
・tinkerとSQL観測で「データ起因」を最短で潰す
・本番は止血→観測→再現→テスト化→恒久対応の順
・キャッシュ問題は optimize:clear を起点に“原因キャッシュ”を特定して手順化
-
前の記事
Laravel Vaporで実現するサーバーレスデプロイ:AWS Lambda前提の設計・設定・運用を一通り揃える 2026.02.07
-
次の記事
記事がありません
コメントを書く