カスタム例外ハンドラーを使用したLaravel404ページの作成
序章
前例のないイベントまたはエラーが発生すると、PHP例外がスローされます。 経験則として、例外はifステートメントなどのアプリケーションロジックを制御するために使用されるべきではなく、Exception
クラスのサブクラスである必要があります。
前例のないため、アプリケーションの任意の時点または時点で例外がスローされる可能性があります。
Laravelは、Laravelアプリケーションでスローされたすべての例外をチェックし、関連する応答を提供する便利な例外ハンドラークラスを提供します。 これは、Laravelで使用されるすべての例外がExceptionクラスを拡張するという事実によって可能になります。
すべての例外を単一のクラスでキャッチすることの主な利点の1つは、例外に応じて異なる応答メッセージを返すカスタム例外ハンドラーを作成できることです。
このチュートリアルでは、Laravel 5.2でカスタム例外ハンドラーを作成する方法と、例外に応じて404ページを返す方法を見ていきます。
使い方
Laravel 5.2では、カスタムとデフォルトの両方のすべてのエラーと例外は、2つのメソッドを使用してapp/Exceptions/Handler.php
のHandler
クラスによって処理されます。
report()
reportメソッドを使用すると、発生した例外をログに記録したり、bugsnagやsentryなどのエラーログエンジンに解析したりできます。これらについてはこのチュートリアルでは詳しく説明しません。
render()
renderメソッドは、例外によって発生したエラーメッセージで応答します。 例外からHTTP応答を生成し、ブラウザに送り返します。
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
return parent::render($request, $e);
}
ただし、独自のカスタム例外ハンドラーを使用して、デフォルトのエラー処理をオーバーライドできます。
/**
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($e instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $e);
}
内部的には、Laravelは独自の処理チェックを実行して、例外に対する可能な限り最良の応答を決定します。 親クラス(Illuminate\Foundation\Exceptions\Handler
)を見ると、renderメソッドは、スローされた例外に応じて異なる応答を生成します。
/**
* Render an exception into a response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, Exception $e)
{
if ($e instanceof HttpResponseException) {
return $e->getResponse();
} elseif ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
} elseif ($e instanceof AuthenticationException) {
return $this->unauthenticated($request, $e);
} elseif ($e instanceof AuthorizationException) {
$e = new HttpException(403, $e->getMessage());
} elseif ($e instanceof ValidationException && $e->getResponse()) {
return $e->getResponse();
}
if ($this->isHttpException($e)) {
return $this->toIlluminateResponse($this->renderHttpException($e), $e);
} else {
return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e);
}
}
LaravelのEloquent例外をスローする
このセクションでは、意図的に例外を発生させて、組み込みのLaravelエラーを作成します。
これを行うには、firstOrFail()
Eloquentメソッドを使用して、モデルから存在しないレコードをフェッチしようとします。
先に進み、簡単なSQLiteデータベースをセットアップします。 幸い、LaravelにはUser
モデルと対応するユーザーテーブルが付属しています。 次のようにするだけです。
- 新しいLaravelプロジェクトを作成します。
.env
ファイルを更新して、DB_CONNECTIONをsqliteおよび唯一のデータベースパラメーターにします。- データベースディレクトリにdatabase.sqliteファイルを作成します。 これは、
config/database.php
で構成されているデフォルトのSQLiteデータベースです。 - Laravelプロジェクトのルートで
php artisan migrate
を実行します。 これにより、データベースにユーザーテーブルが設定されます。
次に、ルートとコントローラーを追加して、usersテーブルの最初のユーザーを取得します。このユーザーはたまたま存在しません。
app / Http / routers.php
Route::get('/user', [
'uses' => 'SampleController@findUser',
'as' => 'user'
]);
App / Http / Controllers / SampleController.php
/**
* Return the first user in the users table
*
* @return Array User details
*/
public function findUser()
{
$user = User::firstOrFail();
return $user->toArray();
}
これをブラウザで実行すると、ModelNotFoundException
エラー応答が返されます。
カスタムハンドラを使用して例外をキャッチする
ModelNotFoundException
この例外を除いて、独自のエラーメッセージを返すカスタムハンドラーを追加できるようになりました。
app/Exceptions/Handler.php
のrender
メソッドを変更して、例外がModelNotFoundException
またはNotFoundHttpException
。
どちらでもない場合は、Laravelに例外を処理させます。
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
//check if exception is an instance of ModelNotFoundException.
if ($e instanceof ModelNotFoundException) {
// ajax 404 json feedback
if ($request->ajax()) {
return response()->json(['error' => 'Not Found'], 404);
}
// normal 404 view page feedback
return response()->view('errors.missing', [], 404);
}
return parent::render($request, $e);
}
resources / view / errorsに404.blade.php
ファイルを追加して、ユーザーからのフィードバックを含めます。
<!DOCTYPE html>
<html>
<head>
<title>User not found.</title>
</head>
<body>
<p>You broke the balance of the internet</p>
</body>
</html>
ここでページを更新すると、ビューに404ステータスコードを含む次のメッセージが表示されます。
NotFoundHttpException
ユーザーが/foo / bar / randomstr1ng などの未定義のルートにアクセスすると、Symfonyパッケージの一部として提供されるNotFoundHttpException
例外がスローされます。
この例外を処理するために、前に変更したrender
メソッドに2番目の条件を追加し、 resources / view / errors /missing.blade.phpからメッセージを返します。
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
//check if exception is an instance of ModelNotFoundException.
//or NotFoundHttpException
if ($e instanceof ModelNotFoundException or $e instanceof NotFoundHttpException) {
// ajax 404 json feedback
if ($request->ajax()) {
return response()->json(['error' => 'Not Found'], 404);
}
// normal 404 view page feedback
return response()->view('errors.missing', [], 404);
}
return parent::render($request, $e);
}
Laravelの中止方法を利用する
前のセクションで行ったように、Laravel 5.2では、スローされた例外に基づいてカスタムエラーページを簡単に作成できます。
オプションの応答メッセージを受け取るabort
メソッドを呼び出すことで、404エラーページ応答を簡単に生成することもできます。
abort(404, 'The resource you are looking for could not be found');
これにより、対応するresources/view/errors/404.blade.php
がチェックされ、404ステータスコードを含むHTTP応答がブラウザに返されます。 同じことが401および500エラーステータスコードにも当てはまります。
結論
アプリケーションの環境に応じて、さまざまなレベルのエラーの詳細を表示したい場合があります。 [X32X]