Laravel 5.6 デフォルトの
例外ハンドリング処理を
まとめてみた
Laravel/Vue.js 勉強会 #4
#laravue ですが
今回は Laravel オンリーの
おなはしです
おことわり
岡田 正平(おかだ しょうへい)@okashoi
• 株式会社ウィルゲート 2015年新卒入社
• 開発室 ソリューションユニット 所属
• PHP, Laravel, Vue.js
3
自己紹介
Slides:
Laravel 5.6 にて
• エラー発生時に所定のフォーマットでログを出力したい
• エラー発生時に所定の slack チャネルに通知を送りたい
• エラー画面のメッセージとログに出力するメッセージを分けたい
4
(背景)やりたかったこと
5
(アプリケーション内で)catch されなかった例外に対する処理を
App¥Exceptions¥Handler に記述すればよさそう
• report: ロギングに関する設定
• render: どのようなレスポンスを返すかの設定
> All exceptions are handled by the App¥Exceptions¥Handler class. This class contains
two methods: report and render. (中略) The report method is used to log exceptions
or send them to an external service like Bugsnag or Sentry. (中略) The render method
is responsible for converting a given exception into an HTTP response that should be sent
back to the browser.
6
よっしゃ、設定するぜ! .
よっしゃ、設定するぜ! .
……
?
• エラーの種類によってログが出力されたりされなかったり、
どうやって実現しているの?
• 結局どのエラーがログ出力されないの?
• したときは report されるの?
• バリデーションエラーのときの挙動はどうやって実現しているの?
10
ところで、デフォルトでは何をやってるのよ?
abort()
まとめてみた
1. 指定された例外については何もせずに終了
• カスタマイズ可能な App¥Exceptions¥Hander の $dontreport に加え
基底クラス Illuminate¥Foundation¥Exceptions¥Handler には
$internalDontReport
2. 例外自信が report() メソッドを持っていたら
優先的にそちらの処理を行って終了
3. それ以外は $logger->error() でログ出力
12
のデフォルトの挙動report()
protected $internalDontReport = [
AuthenticationException::class,
AuthorizationException::class,
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
TokenMismatchException::class,
ValidationException::class,
];
report()
1. 指定された例外については何もせずに終了
• カスタマイズ可能な App¥Exceptions¥Hander の $dontreport に加え
基底クラス Illuminate¥Foundation¥Exceptions¥Handler には
$internalDontReport
2. 例外自信が report() メソッドを持っていたら
優先的にそちらの処理を行って終了
3. それ以外は $logger->error() でログ出力
13
のデフォルトの挙動report()
protected $internalDontReport = [
AuthenticationException::class,
AuthorizationException::class,
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
TokenMismatchException::class,
ValidationException::class,
];
report()
• の中身は HttpException を送出しているだけ
• artisan down によるメンテナンスモードのときは投げられた例外が
最終的に ServiceUnavailableHttpException に変換される
➢ 結果、どちらも report されない
14
のデフォルトの挙動report()report()
abort()
※スペースの都合上、名前空間は省略
1. 例外自身が render 可能なら優先的にそちらを利用して終了
2. 特定の例外を変換
3. 特定の例外については専用の処理を行って終了
例) ValidationException → json レスポンスならエラーレスポンスを返す
そうでなければ前の画面にリダイレクト
4. json レスポンスならエラーレスポンスを返す or
デバッグモードなら詳細表示 or
例外を HttpException に変換してエラー画面を描画
15
のデフォルトの挙動(ざっくり)report()render()
※スペースの都合上、名前空間は省略
1. 例外自身が render 可能なら優先的にそちらを利用して終了
2. 特定の例外を変換
3. 特定の例外については専用の処理を行って終了
例) ValidationException → json レスポンスならエラーレスポンスを返す
そうでなければ前の画面にリダイレクト
4. json レスポンスならエラーレスポンスを返す or
デバッグモードなら詳細表示 or
例外を HttpException に変換してエラー画面を描画
16
のデフォルトの挙動(ざっくり)report()render()
※スペースの都合上、名前空間は省略
protected function prepareException(Exception $e)
{
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
} elseif ($e instanceof AuthorizationException) {
$e = new AccessDeniedHttpException($e->getMessage(), $e);
} elseif ($e instanceof TokenMismatchException) {
$e = new HttpException(419, $e->getMessage(), $e);
}
return $e;
}
1. 例外自身が render 可能なら優先的にそちらを利用して終了
2. 特定の例外を変換
3. 特定の例外については専用の処理を行って終了
例) ValidationException → json レスポンスならエラーレスポンスを返す
そうでなければ前の画面にリダイレクト
4. json レスポンスならエラーレスポンスを返す or
デバッグモードなら詳細表示 or
例外を HttpException に変換してエラー画面を描画
17
のデフォルトの挙動(ざっくり)report()render()
※スペースの都合上、名前空間は省略
→バリデーションエラーのときに
「よしなに」やってくれる挙動は render によるもの
• エラー発生時に所定のフォーマットでログを出力したい
• エラー発生時に所定の slack チャネルに通知を送りたい
• エラー画面のメッセージとログに出力するメッセージを分けたい
19
やりたかったことへの解
report の設定はいじる必要なし
logging の errorlog channel をカスタマイズ
ログ出力したいエラーに abort は使わない
• エラー発生時に所定のフォーマットでログを出力したい
• エラー発生時に所定の slack チャネルに通知を送りたい
• エラー画面のメッセージとログに出力するメッセージを分けたい
20
やりたかったことへの解
エラー画面用メッセージをプロパティとして持った独自例外を定義
render でそのメッセージが表示されるように記述する
※スペースの都合上、名前空間は省略

Laravel 5.6 デフォルトの例外ハンドリング処理をまとめてみた

  • 1.
  • 2.
    #laravue ですが 今回は Laravelオンリーの おなはしです おことわり
  • 3.
    岡田 正平(おかだ しょうへい)@okashoi •株式会社ウィルゲート 2015年新卒入社 • 開発室 ソリューションユニット 所属 • PHP, Laravel, Vue.js 3 自己紹介 Slides:
  • 4.
    Laravel 5.6 にて •エラー発生時に所定のフォーマットでログを出力したい • エラー発生時に所定の slack チャネルに通知を送りたい • エラー画面のメッセージとログに出力するメッセージを分けたい 4 (背景)やりたかったこと
  • 5.
  • 6.
    (アプリケーション内で)catch されなかった例外に対する処理を App¥Exceptions¥Handler に記述すればよさそう •report: ロギングに関する設定 • render: どのようなレスポンスを返すかの設定 > All exceptions are handled by the App¥Exceptions¥Handler class. This class contains two methods: report and render. (中略) The report method is used to log exceptions or send them to an external service like Bugsnag or Sentry. (中略) The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. 6
  • 7.
  • 8.
  • 9.
  • 10.
    • エラーの種類によってログが出力されたりされなかったり、 どうやって実現しているの? • 結局どのエラーがログ出力されないの? •したときは report されるの? • バリデーションエラーのときの挙動はどうやって実現しているの? 10 ところで、デフォルトでは何をやってるのよ? abort()
  • 11.
  • 12.
    1. 指定された例外については何もせずに終了 • カスタマイズ可能なApp¥Exceptions¥Hander の $dontreport に加え 基底クラス Illuminate¥Foundation¥Exceptions¥Handler には $internalDontReport 2. 例外自信が report() メソッドを持っていたら 優先的にそちらの処理を行って終了 3. それ以外は $logger->error() でログ出力 12 のデフォルトの挙動report() protected $internalDontReport = [ AuthenticationException::class, AuthorizationException::class, HttpException::class, HttpResponseException::class, ModelNotFoundException::class, TokenMismatchException::class, ValidationException::class, ]; report()
  • 13.
    1. 指定された例外については何もせずに終了 • カスタマイズ可能なApp¥Exceptions¥Hander の $dontreport に加え 基底クラス Illuminate¥Foundation¥Exceptions¥Handler には $internalDontReport 2. 例外自信が report() メソッドを持っていたら 優先的にそちらの処理を行って終了 3. それ以外は $logger->error() でログ出力 13 のデフォルトの挙動report() protected $internalDontReport = [ AuthenticationException::class, AuthorizationException::class, HttpException::class, HttpResponseException::class, ModelNotFoundException::class, TokenMismatchException::class, ValidationException::class, ]; report()
  • 14.
    • の中身は HttpExceptionを送出しているだけ • artisan down によるメンテナンスモードのときは投げられた例外が 最終的に ServiceUnavailableHttpException に変換される ➢ 結果、どちらも report されない 14 のデフォルトの挙動report()report() abort() ※スペースの都合上、名前空間は省略
  • 15.
    1. 例外自身が render可能なら優先的にそちらを利用して終了 2. 特定の例外を変換 3. 特定の例外については専用の処理を行って終了 例) ValidationException → json レスポンスならエラーレスポンスを返す そうでなければ前の画面にリダイレクト 4. json レスポンスならエラーレスポンスを返す or デバッグモードなら詳細表示 or 例外を HttpException に変換してエラー画面を描画 15 のデフォルトの挙動(ざっくり)report()render() ※スペースの都合上、名前空間は省略
  • 16.
    1. 例外自身が render可能なら優先的にそちらを利用して終了 2. 特定の例外を変換 3. 特定の例外については専用の処理を行って終了 例) ValidationException → json レスポンスならエラーレスポンスを返す そうでなければ前の画面にリダイレクト 4. json レスポンスならエラーレスポンスを返す or デバッグモードなら詳細表示 or 例外を HttpException に変換してエラー画面を描画 16 のデフォルトの挙動(ざっくり)report()render() ※スペースの都合上、名前空間は省略 protected function prepareException(Exception $e) { if ($e instanceof ModelNotFoundException) { $e = new NotFoundHttpException($e->getMessage(), $e); } elseif ($e instanceof AuthorizationException) { $e = new AccessDeniedHttpException($e->getMessage(), $e); } elseif ($e instanceof TokenMismatchException) { $e = new HttpException(419, $e->getMessage(), $e); } return $e; }
  • 17.
    1. 例外自身が render可能なら優先的にそちらを利用して終了 2. 特定の例外を変換 3. 特定の例外については専用の処理を行って終了 例) ValidationException → json レスポンスならエラーレスポンスを返す そうでなければ前の画面にリダイレクト 4. json レスポンスならエラーレスポンスを返す or デバッグモードなら詳細表示 or 例外を HttpException に変換してエラー画面を描画 17 のデフォルトの挙動(ざっくり)report()render() ※スペースの都合上、名前空間は省略 →バリデーションエラーのときに 「よしなに」やってくれる挙動は render によるもの
  • 19.
    • エラー発生時に所定のフォーマットでログを出力したい • エラー発生時に所定のslack チャネルに通知を送りたい • エラー画面のメッセージとログに出力するメッセージを分けたい 19 やりたかったことへの解 report の設定はいじる必要なし logging の errorlog channel をカスタマイズ ログ出力したいエラーに abort は使わない
  • 20.
    • エラー発生時に所定のフォーマットでログを出力したい • エラー発生時に所定のslack チャネルに通知を送りたい • エラー画面のメッセージとログに出力するメッセージを分けたい 20 やりたかったことへの解 エラー画面用メッセージをプロパティとして持った独自例外を定義 render でそのメッセージが表示されるように記述する ※スペースの都合上、名前空間は省略