例外エラーの補足 スタックトレースとトップレベルについて


スタックトレースとは?

スタックトレースというのは

「例外が発生するまでに経てきたメソッド(関数)の履歴」

もう少し砕けた言い方をすると

「あるメソッドでエラーが発生するまでに、どんなメソッドを、どの順番で呼び出したのか。の履歴」

例えばメソッド、methodA、methodB、methodC、methodDがあるとして

methodAの処理の中でmethodBを呼び
methodBの処理の中でmethodCを呼び
methodCの処理の中でmethodDを呼んだところでエラーが発生したとします。(PHP)

function methodA()
{
    methodB();
}

function methodB()
{
    methodC();
}

function methodC()
{
    methodD();
}

function methodD()
{
    return 5 / 0; // 0除算で例外エラー発生
}

echo methodA();

するとこのようなエラー画面が表示されます

エラーが発生した行数が書かれてあり、上からmethodD(#1),methodC(#2),methodB(#3),methodA(#4)と
たどってきているのがわかると思います。

methodDで発生した例外エラー情報が、try~catchで補足されなければ
例外エラー情報は補足されるまで呼び出し元をさかのぼっていき
一番最初の呼び出し元(methodA)でも補足されなければ
Fatal Error(致命的なエラー)となってアプリを即停止させます。

この一番最初の呼び出し元というのが トップレベル です。
(正しくは「クラス/モジュール定義の一番外側のコンテキスト」ですが、まあ難しいのでとりあえずは一番外側=一番最初という理解でいいと思います)

ただし、トップレベルまでさかのぼってきた例外エラーがFatal Errorを出して、ユーザーの画面に上記のような画面が表示されても困ります

代わりにエラー画面を表示させたいけど、例外エラーが出る可能性のある箇所で毎回try~catchを書いて、エラー画面を表示させるという同じ処理を書くのも違う、、

となった時に、トップレベルまでさかのぼってきたエラーをまとめてキャッチ(補足)してエラー画面を表示させたり、ログファイルにエラーの内容を書き出したりする処理をまとめておけるのが
set_exception_handlerという関数です。

この関数をトップレベルでメソッドを呼び出すファイルに記述しておくことで
補足されなかった例外エラーをここでまとめて補足することができ共通の処理を実行できます。

・ある例外エラーは違う処理で、個別に処理がしたいんだ!
というような時にはtry~catchで囲んであげるという形になります。

PHPエラーを例外エラーへ

また、PHPの標準エラー報告を、例外エラーに変換させるような
set_error_handlerという関数もあります

この関数を呼び出しておくことで、通常try~catchでは補足できないPHPエラーも例外エラーとして扱えることができるようになります。

補足: 例外エラーを投げるに意識すること

例外エラーを投げる際のエラークラスには様々なクラスがあり、すべてのクラスはExeptionクラスを基準に階層ツリー構造となっていて、それぞれ発生するエラーの内容によって選択するクラスも変わってきます。(例えば引数の型エラーならInvalidArgmentExeptionを投げる)
キャッチするクラスによってどんなエラーが発生したのかが把握できるので、大元となるExceptionクラス(例外エラーが発生したということしかわからない)を投げてはいけないという原則もあります。このあたりも意識して例外エラーへの対処はしていきたいですね