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

Laravelのエラーハンドリングをカスタマイズする

Kazuhei Arai
December 16, 2020

 Laravelのエラーハンドリングをカスタマイズする

Kazuhei Arai

December 16, 2020
Tweet

More Decks by Kazuhei Arai

Other Decks in Programming

Transcript

  1. ς Ϋ ϊ ϩ δ ʔ ͷ ྗ Ͱ M

    & A ʹ ྲྀ ௨ ֵ ໋ Λ
  2. 1)1ͷ&YDFQUJPO &SSPS͸&YDFQUJPOͰ͸ͳ͍ͷͰ5ISPXBCMFͱͯ͠$BUDI <?php /** * Handle an incoming HTTP request.

    * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function handle($request) { try { throw new SomeException(); } catch (Exception $e) { // ExceptionͷΈCatch } catch (Throwable $e) { // ExceptionͱErrorͷ྆ํΛCatch } }
  3. ΤϥʔϋϯυϦϯά·ͰͷྲྀΕ QVCMJDJOEFYQIQͰ,FSOFMΛੜ੒͠,FSOFMIBOEMF Λ࣮ߦ <?php /** * Laravel - A PHP

    Framework For Web Artisans * * @package Laravel * @author Taylor Otwell <[email protected]> */ define('LARAVEL_START', microtime(true)); /** ུ **/ $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send(); $kernel->terminate($request, $response);
  4. ΤϥʔϋϯυϦϯά·ͰͷྲྀΕ *MMVNJOBUFa'PVOEBUJPOa)UUQa,FSOFMIBOEMF಺Ͱ &YDFQUJPOɺ5ISPXBCMFΛर͏ <?php /** লུ **/ public function handle($request)

    { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new RequestHandled($request, $response) ); return $response; }
  5. ΤϥʔϋϯυϦϯά·ͰͷྲྀΕ &SSPS΋'BUBM5ISPXBCMF&SSPSͱ͍͏໊લͷ &SSPS&YDFQUJPOʹม׵͍ͯ͠Δ <?php /** লུ **/ public function handle($request)

    { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new RequestHandled($request, $response) ); return $response; }
  6. ΤϥʔϋϯυϦϯά·ͰͷྲྀΕ ͭ·Γɺ-BSBWFMͷ࣮ߦ࣌ʹൃੜͨ͠&SSPS͸࠷ऴతʹ શͯ&YDFQUJPOʹม׵͞Ε͔ͯΒॲཧ͞ΕΔ <?php /** লུ **/ public function handle($request)

    { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new RequestHandled($request, $response) ); return $response; }
  7. ΤϥʔϋϯυϦϯά·ͰͷྲྀΕ <?php /** লུ **/ /** * Report the exception

    to the exception handler. * * @param \Exception $e * @return void */ protected function reportException(Exception $e) { $this->app[ExceptionHandler::class]->report($e); } /** * Render the exception to a response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Symfony\Component\HttpFoundation\Response */ protected function renderException($request, Exception $e) { return $this->app[ExceptionHandler::class]->render($request, $e); } ΤϥʔϋϯυϦϯά͸&YDFQUJPO)BOEMFSDMBTTͷ࣮૷͕ߦ͏
  8. ΤϥʔϋϯυϦϯάͷྲྀΕ <?php /** লུ **/ 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 ); } σϑΥϧτͷQSFQBSF3FTQPOTFʹ͸&YDFQUJPOΛड͚औͬͯ ඳը͢Δ࠷௿ݶͷॲཧ͕ॻ͍ͯ͋Δ
  9. ಛఆͷ&YDFQUJPOΛϩάʹग़͞ͳ͘͢Δ EPOU3FQPSUΛࢦఆͯ͠ϩάʹग़͞ͳ͍ <?php namespace Illuminate\Foundation\Exceptions; /** ུ **/ class Handler

    extends ExceptionHandler {
 
 /** ུ **/ protected function shouldntReport(Exception $e) { $dontReport = array_merge($this->dontReport, $this->internalDontReport); return ! is_null(Arr::first($dontReport, function ($type) use ($e) { return $e instanceof $type; })); }
  10. ಛఆͷ&YDFQUJPOΛϩάʹग़͞ͳ͘͢Δ EPOU3FQPSUΛࢦఆͯ͠ϩάʹग़͞ͳ͍ <?php namespace App\Exceptions; /** ུ **/ class Handler

    extends ExceptionHandler { /** * A list of the exception types that are not reported. * * @var array */ protected $dontReport = [ PreconditionException::class, NotFoundException::class, ];
  11. ಠࣗͷ&YDFQUJPOͰطଘͷΤϥʔදࣔΛ͢Δ )UUQ&YDFQUJPOΛܧঝͨ͠Ϋϥεʹม׵͢Δ <?php namespace App\Exceptions; /** ུ **/ class Handler

    extends ExceptionHandler { protected function prepareException(Exception $e) { $e = parent::prepareException($e); if ($e instanceof NotFoundException) { $e = new NotFoundHttpException($e->getMessage(), $e); } if ($e instanceof PreconditionException) { $e = new AccessDeniedHttpException($e->getMessage(), $e); } return $e; }
  12. ΤϥʔදࣔͷWJFXΛΧελϚΠζ͢Δ <?php namespace App\Exceptions; /** ུ **/ class Handler extends

    ExceptionHandler { protected function prepareResponse($request, Exception $e) { return $this->toIlluminateResponse( $this->customRenderHttpException($request, $e), $e ); } private function customRenderHttpException(Request $request, HttpException $e) { $status = $e->getStatusCode(); $paths = collect(config('view.paths')); view()->replaceNamespace('errors', $paths->map(function ($path) use ($request) { if ($request->is('admin/*')) { return "{$path}/admin/errors"; } return "{$path}/service/errors"; })->push(__DIR__ . '/views')->all());
 
 if (view()->exists($view = "errors::{$status}")) { return response()->view($view, ['exception' => $e], $status, $e->getHeaders()); } return $this->convertExceptionToResponse($e); }