2019-05-22 開催の「Laravel Meetup Tokyo Vol.12」におけるLT資料です
https://laravel-meetup-tokyo.connpass.com/event/124314
Τϥʔ࣌ʹϩάʹग़ྗ͢Δใͱը໘ʹදࣔ͢ΔใΛ͚Δokashoi@Laravel Meetup Tokyo Vol.12
View Slide
͓·͑ͩΕʁ• Ԭా ਖ਼ฏʗ͓͔͠ΐ͍• גࣜձࣾΟϧήʔτ• ΞʔΩςΫτ ݉ ٕज़ใ ← New!!• ٕज़ॻయ 6 Ͱٕज़ಉਓࢽσϏϡʔͨ͠• ͜ͷ LT ͦͷ 1 খઅΑΓ• Ԡ͋Δͱخ͍͠Ͱ͢🙇 #LaravelTokyo!2
Γ͍ͨ͜ͱ!3
Γ͍ͨ͜ͱ!4Τϥʔʢ˞ʣൃੜ࣌˞ΞϓϦέʔγϣϯίʔυͰϋϯυϦϯά͞Εͳ͔ͬͨྫ֎
Γ͍ͨ͜ͱ!5Τϥʔʢ˞ʣൃੜ࣌ ϨεϙϯεͱϩάͷϝοηʔδΛ ͦΕͧΕҟͳΔͷʹ͍ͨ͠˞ΞϓϦέʔγϣϯίʔυͰϋϯυϦϯά͞Εͳ͔ͬͨྫ֎
ϕʔεͱͳͬͨΞΠσΞhttps://speakerdeck.com/suzuken/phpcon2017!6
ͳΜͰΓ͍ͨͷʁ• Ϣʔβ͚ը໘ʹγεςϜʹؔ͢ΔϝοηʔδΛදࣔͯ͠͠·͏• Ϣʔβͷؔ৺͝ͱͰͳ͍ʗແ༻ͳࠞཚΛੜΉ• ηΩϡϦςΟతͳϦεΫ͕͋Δ• ϩάʹϢʔβ͚ϝοηʔδ͔͠ग़ྗ͞Ε͍ͯͳ͍• Λղফ͢Δख͕͔ΓʹͳΒͳ͍ʢʮΤϥʔ͕ൃੜ͠·ͨ͠ʯʣ!7
࣮ݱํ๏Λͻͱ͜ͱͰ·ͱΊΔͱಠࣗྫ֎ʹɺࣗΛ HttpException ม͢ΔϝιουΛͭ͘Δͱָ😄!8
ΞδΣϯμ• Γ͍ͨ͜ͱ ←DONE• σϑΥϧτͷΤϥʔϋϯυϦϯάͷڍಈ• ࣮ݱख๏!9
ΞδΣϯμ• Γ͍ͨ͜ͱ• σϑΥϧτͷΤϥʔϋϯυϦϯάͷڍಈ• ࣮ݱख๏!10
• App\Exceptions\Handler ʹྫ֎ϋϯυϦϯάॲཧ͕ॻ͚Δ• ϩΪϯάʹؔ͢Δڍಈ report()• HTTP Ϩεϙϯεʹؔ͢Δڍಈ render()• جఈΫϥε Illuminate\Foundation\Exceptions\Handler
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);}
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 ՄೳͳΒ༏ઌతʹͦΕΛར༻
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);}ಛఆͷྫ֎Λผͷྫ֎ʹม
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);}ಛఆͷྫ֎ʹ͍ͭͯઐ༻ͷॲཧΛͯ͠ऴྃ
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 ʹΑΔ੍ޚʣ
ΞδΣϯμ• Γ͍ͨ͜ͱ• σϑΥϧτͷΤϥʔϋϯυϦϯάͷڍಈ• ࣮ݱख๏!18
ಠࣗྫ֎ΛఆٛʢҰྫʣ!19namespace 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;}
ಠࣗྫ֎ΛఆٛʢҰྫʣ!20namespace 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 Ϩεϙϯεੜʹ༻͍Δ
ಠࣗྫ֎ΛఆٛʢҰྫʣ!21namespace 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;}͜ΕΛܧঝ͠ɺఆٛͨ͠ΤϥʔʹରԠ͢Δྫ֎Λ࣮͢Δ
App\Exceptions\Handler ΛΧελϚΠζ• ࠓճ report() ͦͷ··Ͱ 🙆• Τϥʔ࣌ͷ HTTP ϨεϙϯεΛ ಠࣗྫ֎ͷ getStatusCode() ͱ getUserMessage() Λͬͯੜ͍ͨ͠• → ͪΐͬͱָ͢Δํ๏Λ͝հ!22
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);}࠶ܝ
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);}࠶ܝ
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);}
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 Ϩεϙϯεʹมͯ͘͠ΕΔ
ಠࣗྫ֎Λ HttpException ʹ มͰ͖Δͱָ😄!27
ಠࣗྫ֎Λ HttpException ʹมͰ͖Δͱָ😄!28namespace 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 Ϩεϙϯεͷํ͏·͍͖͘·͢
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);}Ճ
͍ํ!30namespace 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 Ϩεϙϯε༻ͷϝοηʔδʹ ΞΫηεՄೳ
·ͱΊಠࣗྫ֎ʹɺࣗΛ HttpException ม͢ΔϝιουΛͭ͘Δͱָ😄!31
⾠ҙ• ʮྫ֎ΛͲ͏͏͔ʯʹ͍͍ͭͯΖ͍Ζͳݟղ͕͋Δͱࢥ͍·͢• Laravel Ͱ 404 ͷΫϥΠΞϯτΤϥʔʹྫ֎Λ͍ͬͯΔͷͰ ͦΕʹͷͬͱͬͯྫ֎Λ͏ͱ͍͏ํ๏Λ࠾༻͠·ͨ͠!32
આ໌ͨ͠ιʔείʔυ +α Լه URL ʹࡌ͍ͤͯ·͢https://github.com/okashoi/colab-techbook6-example!33
!34
ʢʣฤूͷաఔͰল͍ͨ εϥΠυ܊!35
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]));}
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]));}ࢦఆ͞Εͨྫ֎ʹ͍ͭͯԿͤͣʹऴྃ
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() ϝιουΛ͍࣋ͬͯͨΒ༏ઌతʹͦΕΛར༻
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 Λϩάग़ྗ