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

エラー時にログに出力する情報と画面に表示する情報を分ける #LaravelTokyo

エラー時にログに出力する情報と画面に表示する情報を分ける #LaravelTokyo

2019-05-22 開催の「Laravel Meetup Tokyo Vol.12」におけるLT資料です

https://laravel-meetup-tokyo.connpass.com/event/124314

Shohei Okada

May 22, 2019
Tweet

More Decks by Shohei Okada

Other Decks in Programming

Transcript

  1. ͓·͑ͩΕʁ • Ԭా ਖ਼ฏʗ͓͔͠ΐ͍ • גࣜձࣾ΢Οϧήʔτ • ΞʔΩςΫτ ݉ ٕज़޿ใ

    ← New!! • ٕज़ॻయ 6 Ͱٕज़ಉਓࢽσϏϡʔͨ͠ • ͜ͷ LT ͸ͦͷ 1 খઅΑΓ • ൓Ԡ͋Δͱخ͍͠Ͱ͢🙇 #LaravelTokyo !2
  2. Illuminate\Foundation\Exceptions\Handler::render() !13 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); }
  3. Illuminate\Foundation\Exceptions\Handler::render() !14 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } ྫ֎ࣗ৴͕ render ՄೳͳΒ༏ઌతʹͦΕΛར༻
  4. Illuminate\Foundation\Exceptions\Handler::render() !15 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } ಛఆͷྫ֎Λผͷྫ֎ʹม׵
  5. Illuminate\Foundation\Exceptions\Handler::render() !16 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } ಛఆͷྫ֎ʹ͍ͭͯઐ༻ͷॲཧΛͯ͠ऴྃ
  6. Illuminate\Foundation\Exceptions\Handler::render() !17 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } ͦΕҎ֎͸ྫ֎ΛΤϥʔϨεϙϯεʹม׵ ʢContet-Type ΍σόοάϞʔυͷ ON/OFF ౳ʹΑΔ੍ޚʣ
  7. ಠࣗྫ֎ΛఆٛʢҰྫʣ !19 <?php namespace App\Exceptions; /** * Class MyAppException *

    @package App\Exceptions */ abstract class MyAppException extends \Exception { /** * @return int HTTP ステータスコード */ abstract public function getStatusCode(): int; /** * @return string ユーザ向けのメッセージ */ abstract public function getUserMessage(): string; }
  8. ಠࣗྫ֎ΛఆٛʢҰྫʣ !20 <?php namespace App\Exceptions; /** * Class MyAppException *

    @package App\Exceptions */ abstract class MyAppException extends \Exception { /** * @return int HTTP ステータスコード */ abstract public function getStatusCode(): int; /** * @return string ユーザ向けのメッセージ */ abstract public function getUserMessage(): string; } HTTP Ϩεϙϯεੜ੒ʹ༻͍Δ
  9. ಠࣗྫ֎ΛఆٛʢҰྫʣ !21 <?php namespace App\Exceptions; /** * Class MyAppException *

    @package App\Exceptions */ abstract class MyAppException extends \Exception { /** * @return int HTTP ステータスコード */ abstract public function getStatusCode(): int; /** * @return string ユーザ向けのメッセージ */ abstract public function getUserMessage(): string; } ͜ΕΛܧঝ͠ɺ ఆٛͨ͠ΤϥʔʹରԠ͢Δྫ֎Λ࣮૷͢Δ
  10. App\Exceptions\Handler ΛΧελϚΠζ • ࠓճ͸ report() ͸ͦͷ··Ͱ 🙆 • Τϥʔ࣌ͷ HTTP

    ϨεϙϯεΛ
 ಠࣗྫ֎ͷ getStatusCode() ͱ getUserMessage() Λ࢖ͬͯੜ੒͍ͨ͠ • → ͪΐͬͱָ͢Δํ๏Λ͝঺հ !22
  11. Illuminate\Foundation\Exceptions\Handler::render() !23 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } ࠶ܝ
  12. Illuminate\Foundation\Exceptions\Handler::render() !24 /** * Render an exception into a response.

    * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } ࠶ܝ
  13. Illuminate\Foundation\Exceptions\Handler::prepareResponse() !25 /** * Prepare a response for the given

    exception. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Symfony\Component\HttpFoundation\Response */ protected function prepareResponse($request, Exception $e) { if (! $this->isHttpException($e) && config('app.debug')) { return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e); } if (! $this->isHttpException($e)) { $e = new HttpException(500, $e->getMessage()); } return $this->toIlluminateResponse( $this->renderHttpException($e), $e ); }
  14. Illuminate\Foundation\Exceptions\Handler::prepareResponse() !26 /** * Prepare a response for the given

    exception. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Symfony\Component\HttpFoundation\Response */ protected function prepareResponse($request, Exception $e) { if (! $this->isHttpException($e) && config('app.debug')) { return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e); } if (! $this->isHttpException($e)) { $e = new HttpException(500, $e->getMessage()); } return $this->toIlluminateResponse( $this->renderHttpException($e), $e ); } Symfony\Component\HttpKernel\Exception\HttpException Λ
 Α͠ͳʹ HTTP Ϩεϙϯεʹม׵ͯ͘͠ΕΔ
  15. ಠࣗྫ֎Λ HttpException ʹม׵Ͱ͖Δͱָ😄 !28 <?php namespace App\Exceptions; use Symfony\Component\HttpKernel\Exception\HttpException; /**

    * Class MyAppException * @package App\Exceptions */ abstract class MyAppException extends \Exception { /** * @return int HTTP ステータスコード */ abstract public function getStatusCode(): int; /** * @return string ユーザ向けのメッセージ */ abstract public function getUserMessage(): string; /** * @return HttpException */ public function toHttpException(): HttpException { return new HttpException( $this->getStatusCode(), $this->getUserMessage(), $this->getPrevious(), [], $this->code ); } } ௥Ճ ※આ໌͸ল͖·͕͢ JSON Ϩεϙϯεͷํ΋͏·͍͖͘·͢
  16. App\Exceptions\Handler ΛΧελϚΠζ !29 /** * Render an exception into an

    HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $exception * @return \Illuminate\Http\Response */ public function render($request, Exception $exception) { // 既存の render の仕組みを活用するため、HttpException に変換する if ($exception instanceof MyAppException) { $exception = $exception->toHttpException(); } return parent::render($request, $exception); } ௥Ճ
  17. ࢖͍ํ !30 <?php namespace App\Exceptions; use Throwable; /** * Class

    HogeException * @package App\Exceptions */ abstract class HogeException extends MyAppException { /** * @return int HTTP ステータスコード */ public function getStatusCode(): int { return 500; } /** * @return string ユーザ向けのメッセージ */ public function getUserMessage(): string { return 'ごめん'; } } • ಠࣗྫ֎ͷ۩৅ΫϥεΛఆٛ • throw new HogeException('エラーです');
 ͷΑ͏ʹͯ͠ྫ֎Λૹग़ • ϩάʹ͸ϩά༻ͷϝοηʔδ͕ه࿥͞ΕΔ • Blade ςϯϓϨʔτ಺Ͱ͸
 $exception->getMessage()
 ͰHTTP Ϩεϙϯε༻ͷϝοηʔδʹ
 ΞΫηεՄೳ
  18. !34

  19. Illuminate\Foundation\Exceptions\Handler::report() !36 /** * Report or log an exception. *

    * @param \Exception $e * @return mixed * * @throws \Exception */ public function report(Exception $e) { if ($this->shouldntReport($e)) { return; } if (is_callable($reportCallable = [$e, 'report'])) { return $this->container->call($reportCallable); } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; } $logger->error( $e->getMessage(), array_merge($this->context(), ['exception' => $e] )); }
  20. Illuminate\Foundation\Exceptions\Handler::report() !37 /** * Report or log an exception. *

    * @param \Exception $e * @return mixed * * @throws \Exception */ public function report(Exception $e) { if ($this->shouldntReport($e)) { return; } if (is_callable($reportCallable = [$e, 'report'])) { return $this->container->call($reportCallable); } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; } $logger->error( $e->getMessage(), array_merge($this->context(), ['exception' => $e] )); } ࢦఆ͞Εͨྫ֎ʹ͍ͭͯ͸Կ΋ͤͣʹऴྃ
  21. Illuminate\Foundation\Exceptions\Handler::report() !38 /** * Report or log an exception. *

    * @param \Exception $e * @return mixed * * @throws \Exception */ public function report(Exception $e) { if ($this->shouldntReport($e)) { return; } if (is_callable($reportCallable = [$e, 'report'])) { return $this->container->call($reportCallable); } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; } $logger->error( $e->getMessage(), array_merge($this->context(), ['exception' => $e] )); } ྫ֎ࣗ৴͕ report() ϝιουΛ͍࣋ͬͯͨΒ ༏ઌతʹͦΕΛར༻
  22. Illuminate\Foundation\Exceptions\Handler::report() !39 /** * Report or log an exception. *

    * @param \Exception $e * @return mixed * * @throws \Exception */ public function report(Exception $e) { if ($this->shouldntReport($e)) { return; } if (is_callable($reportCallable = [$e, 'report'])) { return $this->container->call($reportCallable); } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; } $logger->error( $e->getMessage(), array_merge($this->context(), ['exception' => $e] )); } ͦΕҎ֎͸ྫ֎ͷϝοηʔδͱ context Λϩάग़ྗ