📚

【PHP】スタックトレース(stack trace)の読み方と構造を理解する

に公開

はじめに

PHPで開発し動作確認をしたときに、Stack traceという言葉を見たことがある方がほとんどだと思います。

PHPで例外やエラーが発生したときに表示されるスタックトレース(stack trace)には、エラーの発生場所とその呼び出し経路が表示されます。

この記事では、スタックトレースの基本的な読み方・構造・開発時の活用ポイントを整理します。

スタックトレースとは?

スタックトレースは「関数やメソッドの呼び出し履歴の一覧」です。
エラーや例外が発生したときに、どこで・どのような経路でその場所に到達したかを知るために使います。

PHPでは、上から下に向かって最新の呼び出し(エラー発生地点)→ 呼び出し元の順で出力されます。

実際のコード例とトレース出力

<?php
function foo() {
    bar();
}
function bar() {
    throw new Exception("エラー発生");
}
foo();
出力結果
Fatal error: Uncaught Exception: エラー発生 in /path/to/example.php:6
Stack trace:
#0 /path/to/example.php(3): bar()
#1 /path/to/example.php(8): foo()
#2 {main}

呼び出しの流れとスタックの順序

実際の呼び出し順
{main} → foo() → bar()
スタックに積み重なる順
bar()  # 2番目
foo()  # 1番目
{main} # 0番目

LIFO(Last In First Out)構造に基づいています。

スタックトレースの出力順
#2 {main}
#1 foo()
#0 bar() ← エラーが発生した場所

上記のスタックの積み上がり順と逆になっていることがわかります。

呼び出し順とスタックトレースの出力順まとめ

順序 呼び出し順(処理の流れ) スタックトレースの出力
1 {main} #2 {main}
2 foo() #1 foo()
3 bar()(エラー発生) #0 bar()

#0 {main}の意味とは?

スタックトレースで {main} が出るケースがあります。

  • PHPファイルが「コマンドラインなどから直接実行された」場合に表示される

  • {main} は仮想的なトップレベルの実行コンテキスト

※トップレベルの実行コンテキスト:関数やメソッドの外(=グローバルスコープ)でコードが実行されたことを意味します。

つまり、ファイルの中で最初に処理される部分を指します。

エラーが #0 に出る理由

PHPのスタックトレースは、最後に呼ばれた関数=エラーが発生した位置から出力を始めるため。
そのため、一番上の #0 が最も内側の関数呼び出し(エラー発生位置)を表します。

できること

したがって、#0 を見ると、エラーの発生地点がすぐにわかります。
また、下から上に向かって読むことで、どの関数がどこから呼ばれたかを辿ることができます。

#0 {main} しか表示されないケース

これは、トップレベルのコード(関数の外)で直接エラーが発生した場合です。
このときは呼び出し履歴が存在しないため、スタックに {main} しか載りません。
つまり、関数やクラスの呼び出し以外の最初のコード領域に問題があるということを意味します。

まとめ

  • スタックトレースは、エラー発生までの呼び出し履歴を上から順に示す
  • #0 がエラー発生位置
  • {main} はスクリプトが直接実行された場合のトップレベルスコープ
  • 出力は LIFO 構造(後から呼ばれたものが先に戻る)
  • #0 {main} のみ表示される場合は、関数の外で直接エラーが起きている

参考URL

https://www.php.net/manual/ja/error.gettrace.php

https://wa3.i-3-i.info/word13281.html

https://qiita.com/turituri08/items/9b72392fb0815f2298f8

Discussion