例外クラスを利用したエラーハンドラ
前節でエラーハンドラのカスタマイズとして、Handlerクラスのreport()メソッドとrender()メソッドの記述方法を紹介しました。本節では、同じくエラーハンドラのカスタマイズ方法として、もうひとつ別の方法を紹介しましょう。
例外クラス内に記述できるreport()とrender()
Handlerクラスに記述したreport()メソッドとrender()メソッドの両メソッドは、実は、例外クラスにも記述することができます。例えば、ファイルにアクセスする処理中に、該当ファイルが見つからないなどの致命的な問題がある場合に発生する独自例外としてFileAccessExceptionがあるとします。この例外が発生した場合は、report()メソッドの処理としてメールの送信を、render()メソッドの処理として独自の例外画面を表示させるとします。
前節で紹介したように、report()、および、render()メソッド内に次のような分岐を記述しても問題なく動作します。
if($exception instanceof FileAccessException) { : }
一方で、FileAccessExceptionクラスそのものに、次のようにreport()、および、render()メソッドを記述してしまうこともできます。
<<?php namespace App\Exceptions; use Exception; use Illuminate\Http\Request; use Illuminate\Http\Response; class FileAccessException extends Exception { public function report(): void { // メール送信処理 } public function render(Request $request): Response { $data["errorMsg"] = $this->getMessage(); return response()->view("errors.custom", $data); } }
report()メソッドとrender()メソッド内の記述方法は、前節で紹介したHandlerクラスでの記述方法と同じです。ただし、そもそも例外クラス内での記述ですので、発生した例外クラスに応じての分岐が不要となり、そのため、両メソッドの引数から発生した例外を表す$exceptionがなくなっています。
例外クラスに記述するかHandlerクラスに記述するか
このように、独自例外クラス内にreport()メソッドとrender()メソッドを記述することで、Handlerクラスに記述するよりも、その例外が発生した場合にどのような記録処理と表示処理が行われるのか一目瞭然となり、ソースコードの見通しがよくなります。
そういった意味で、Handlerクラスをカスタマイズするのではなく、各例外クラスにreport()メソッドとrender()メソッドを記述する方式のほうがいいのかというと、そうとも言い切れないところがあります。
というのは、例外クラスにreport()メソッドを記述すると、デフォルトの記録処理、つまり、Handlerクラスではparent::report()と記述していた処理は行われません。そういった意味で、先に紹介したデフォルトの記録処理と独自の記録処理を組み合わせた処理というのは行えません。
また、render()メソッドにしても、例えば、どの独自例外が発生しても、表示させる画面も同じならば、同じ処理コードが各々の例外クラスに散在することになります。その場合は、Handlerクラスをカスタマイズしたほうがスッキリします。
例外が発生した際の処理コードとして、デフォルトの記録処理と組み合わせるのかどうか、各々の例外においてどれくらい共通処理が含まれているのかで、Handlerクラスをカスタマイズするのか、例外クラス内にエラーハンドラ処理コードを記述するのかの切り分けを行えばいいでしょう。
まとめ
今回は、Laravelアプリケーション内でエラーや例外が発生した際の処理として、エラーハンドラとそのカスタマイズを紹介しました。
次回は、Laravelのバリデーション機能を紹介します。