Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Laravel 5.6 デフォルトの例外ハンドリング処理をまとめてみた / Behavior of Laravel 5.6's Exception Handler

Laravel/Vue.js 勉強会 #4 のLT資料です

https://laravue.connpass.com/event/82296/

Shohei Okada

April 25, 2018
Tweet

More Decks by Shohei Okada

Other Decks in Programming

Transcript

  1. Laravel 5.6 にて • エラー発生時に所定のフォーマットでログを出力したい • エラー発生時に所定の slack チャネルに通知を送りたい •

    エラー画面のメッセージとログに出力するメッセージを分けたい 4 (背景)やりたかったこと
  2. 5

  3. (アプリケーション内で)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
  4. • エラーの種類によってログが出力されたりされなかったり、 どうやって実現しているの? • 結局どのエラーがログ出力されないの? • したときは report されるの? •

    バリデーションエラーのときの挙動はどうやって実現しているの? 10 ところで、デフォルトでは何をやってるのよ? abort()
  5. 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()
  6. 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()
  7. • の中身は HttpException を送出しているだけ • artisan down によるメンテナンスモードのときは投げられた例外が 最終的に ServiceUnavailableHttpException

    に変換される ➢ 結果、どちらも report されない 14 のデフォルトの挙動 report() report() abort() ※スペースの都合上、名前空間は省略
  8. 1. 例外自身が render 可能なら優先的にそちらを利用して終了 2. 特定の例外を変換 3. 特定の例外については専用の処理を行って終了 例) ValidationException

    → json レスポンスならエラーレスポンスを返す そうでなければ前の画面にリダイレクト 4. json レスポンスならエラーレスポンスを返す or デバッグモードなら詳細表示 or 例外を HttpException に変換してエラー画面を描画 15 のデフォルトの挙動(ざっくり) report() render() ※スペースの都合上、名前空間は省略
  9. 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; }
  10. 1. 例外自身が render 可能なら優先的にそちらを利用して終了 2. 特定の例外を変換 3. 特定の例外については専用の処理を行って終了 例) ValidationException

    → json レスポンスならエラーレスポンスを返す そうでなければ前の画面にリダイレクト 4. json レスポンスならエラーレスポンスを返す or デバッグモードなら詳細表示 or 例外を HttpException に変換してエラー画面を描画 17 のデフォルトの挙動(ざっくり) report() render() ※スペースの都合上、名前空間は省略 →バリデーションエラーのときに 「よしなに」やってくれる挙動は render によるもの
  11. • エラー発生時に所定のフォーマットでログを出力したい • エラー発生時に所定の slack チャネルに通知を送りたい • エラー画面のメッセージとログに出力するメッセージを分けたい 20 やりたかったことへの解

    エラー画面用メッセージをプロパティとして持った独自例外を定義 render でそのメッセージが表示されるように記述する ※スペースの都合上、名前空間は省略