イントロダクション
新しいLaravelプロジェクトを開始する時点で、エラーと例外の処理はあらかじめ設定済みです。App\Exceptions\Handler
クラスはアプリケーションで発生する全例外をログし、ユーザーへ表示するためのクラスです。このドキュメントでは、このクラスの詳細を確認します。
設定
アプリケーションエラー発生時にユーザーに対し表示する詳細の表示量は、config/app.php
設定ファイルのdebug
設定オプションで決定します。デフォルト状態でこの設定オプションは、.env
ファイルで指定されるAPP_DEBUG
環境変数の値を反映します。
local環境ではAPP_DEBUG
環境変数をtrue
に設定すべきでしょう。実働環境ではこの値をいつもfalse
にすべきです。実働環境でこの値をtrue
にしてしまうと、アプリケーションのエンドユーザーへ、セキュリティリスクになりえる設定情報を表示するリスクを犯すことになります。
例外ハンドラ
例外のレポート
例外はすべて、App\Exceptions\Handler
クラスで処理されます。このクラスはカスタム例外レポーターとレンダラのコールバックを登録するためのregister
メソッドを持っています。このコンセプトを詳細に確認していきましょう。例外レポーターは例外をログするか、FlareやBugSnag、Sentryのような外部サービスへ送信するために使います。デフォルトではログ設定に基づき、例外をログします。しかし、お望みであれば自由に例外をログできます。
たとえば異なった例外を別々の方法でレポートする必要がある場合、reportable
メソッドを使用して、特定のタイプの例外を報告する必要があるときに実行するクロージャを登録できます。Laravelはクロージャのタイプヒントを調べ、クロージャが報告する例外のタイプを推測します。
use App\Exceptions\CustomException;
/**
* アプリケーションの例外処理コールバックの登録
*
* @return void
*/
public function register()
{
$this->reportable(function (CustomException $e) {
//
});
}
reportable
メソッドを使用しカスタム例外レポートコールバックを登録する場合でも、Laravelはアプリケーションのデフォルトログ設定を使い例外をログします。デフォルトログスタックへその例外が伝わるのを止めたい場合は、レポートコールバックの定義時にstop
メソッドを使用するか、コールバックからfalse
を返してください。
$this->reportable(function (CustomException $e) {
//
})->stop();
$this->reportable(function (CustomException $e) {
return false;
});
Tip!! 指定した例外に対する例外レポートをカスタマイズするには、reportable例外を使用することも一考してください。
グローバルログコンテキスト
Laravelは可能である場合、文脈上のデータとしてすべての例外ログへ、現在のユーザーのIDを自動的に追加します。アプリケーションのApp\Exceptions\Handler
クラスにある、context
メソッドをオーバーライドすることにより、独自のグローバルコンテキストデータを定義できます。この情報は、アプリケーションにより書き出されるすべての例外ログメッセージに含まれます。
/**
* ログのデフォルトコンテキスト変数の取得
*
* @return array
*/
protected function context()
{
return array_merge(parent::context(), [
'foo' => 'bar',
]);
}
report
ヘルパ
例外のレポートは必要だが、現在のリクエストの処理は続行したい場合もあります。report
ヘルパ関数は、エラーページをレンダリングせずに、例外ハンドラを使用し簡単にレポートできます。
public function isValid($value)
{
try {
// 値の確認…
} catch (Throwable $e) {
report($e);
return false;
}
}
タイプによる例外の無視
例外ハンドラの$dontReport
プロパティは、ログしない例外のタイプの配列で構成します。たとえば、404エラー例外と同様に、他のタイプの例外もログしたくない場合です。必要に応じてこの配列へ、他の例外を付け加えてください。
/**
* レポートしない例外のリスト
*
* @var array
*/
protected $dontReport = [
\Illuminate\Auth\AuthenticationException::class,
\Illuminate\Auth\Access\AuthorizationException::class,
\Symfony\Component\HttpKernel\Exception\HttpException::class,
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Illuminate\Validation\ValidationException::class,
];
例外のレンダー
Laravelの例外ハンドラはデフォルトで例外をHTTPレスポンスに変換します。しかし、自由に特定のタイプの例外をレンダリングするカスタムクロージャを登録することもできます。例外ハンドラのrenderable
メソッドにより実現します。Laravelはクロージャのタイプヒントを調べ、クロージャがレンダーする例外のタイプを推測します。
use App\Exceptions\CustomException;
/**
* アプリケーションの例外処理コールバックの登録
*
* @return void
*/
public function register()
{
$this->renderable(function (CustomException $e, $request) {
return response()->view('errors.custom', [], 500);
});
}
Reportable/Renderable例外
例外ハンドラの中のreport
とrender
メソッドの中で、例外のタイプをチェックする代わりに、自身のカスタム例外でreport
とrender
メソッドを定義できます。これらのメソッドが存在すると、フレームワークにより自動的に呼び出されます。
<?php
namespace App\Exceptions;
use Exception;
class RenderException extends Exception
{
/**
* 例外のレポート
*
* @return void
*/
public function report()
{
//
}
/**
* 例外をHTTPレスポンスへレンダー
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
return response(...);
}
}
明確な条件と一致する場合のみ実行されるレポートのカスタムロジックが例外に含まれている場合、デフォルトの例外処理の設定を使用し、その例外をレポートするようにLaravelへ指示する必要があるでしょう。そのためには例外のreport
メソッドからfalse
を返してください。
/**
* 例外のレポート
*
* @return bool|void
*/
public function report()
{
// 例外がカスタムレポートする必要があるかを決める
return false;
}
Tip!!
report
メソッドに必要な依存をタイプヒントで指定することで、Laravelのサービスコンテナによりメソッドへ、自動的に依存注入されます。
HTTP例外
例外の中にはサーバでのHTTPエラーコードを表しているものがあります。たとえば「ページが見つかりません」エラー(404)や「未認証エラー」(401)、開発者が生成した500エラーなどです。アプリケーションのどこからでもこの種のレスポンスを生成するには、abortヘルパを使用します。
abort(404);
カスタムHTTPエラーページ
さまざまなHTTPステータスコードごとに、Laravelはカスタムエラーページを簡単に返せます。たとえば404 HTTPステータスコードに対してカスタムエラーページを返したければ、resources/views/errors/404.blade.php
を作成してください。このファイルはアプリケーションで起こされる全404エラーに対し動作します。ビューはこのディレクトリに置かれ、対応するHTTPコードと一致した名前にしなくてはなりません。abort
ヘルパが生成するHttpException
インスタンスは、$exception
変数として渡されます。
<h2>{{ $exception->getMessage() }}</h2>
Laravelのエラーページテンプレートは、vendor:publish
Artisanコマンドでリソース公開できます。テンプレートをリソース公開したら、好みのようにカスタマイズできます。
php artisan vendor:publish --tag=laravel-errors