— y2sunlight 2020-05-09
関連記事
エラー画面を表示するアクションメソッドは通常の(リクエストルータ経由の)アクションとは異なり、集約例外ハンドラーから呼び出されます。このアクションメソッドの設定は以下の設定ファイルで行います。 これは既に各種コアクラスの集約エラーハンドラの項で説明済ですが、念のため以下に再掲しておきます。
/apricot/config/setting
<?php return [ 'debug' => env('APP_DEBUG',false), 'controller' => \App\Exceptions\UncaughtExceptionHandler::class, 'action' => 'render', ];
集約例外ハンドラーから呼び出されるコントローラを集約例外コントローラと呼びます。whoops.setting.php での設定に従い UncaughtExceptionHandler@render メソッドが実行されてエラー画面を表示します。以下に集約例外コントローラを示します。
/apricot/app/Exceptions
<?php namespace App\Exceptions; /** * Uncaught Exception Handler */ class UncaughtExceptionHandler { /** * Render uncaught exception * @param \Throwable $exception */ public function render(\Throwable $exception) { if ($exception instanceof \Core\Exceptions\TokenMismatchException) { // CSRFエラーなどのトークンエラーは419(Page Expired) $status_code = 419; } elseif ($exception instanceof \Core\Exceptions\HttpException) { $status_code = $exception->getStatusCode(); } else { // その他のエラーは500(Internal Server Error) $status_code = 500; } // エラー画面を表示する render('error.exception', ['status_code'=>$status_code])->commit($status_code); } }
abort()
によるHTTP例外 )はそのステータスコードを使用
エラー画面のレイアウトは以下の2つのHTMLテンプレートから成っています。
テンプレート error.exception は、error.layout から継承して作成します。
以下にエラー画面共通のレイアウト( error.layout )を示します。CSSやJavaScriptも使用せずに出来るだけシンプルなHTMLになっています。
/apricot/assets/views/error
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{{__('messages.app.title')}}</title> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css"> <!-- Styles --> <style> html, body { background-color: #fff; color: #636b6f; font-family: 'Nunito', sans-serif; font-weight: 100; height: 100vh; margin: 0; } .full-height { height: 100vh; } .flex-center { align-items: center; display: flex; justify-content: center; } .flex-row { flex-direction: column; } .position-ref { position: relative; } .code { border-right: 2px solid; font-size: 26px; padding: 0 15px 0 15px; text-align: center; } .message { font-size: 18px; text-align: center; } .mb { margin-bottom:1em; } </style> </head> <body> <div class="flex-center position-ref full-height"> @yield('content') </div> </body> </html>
以下に集約例外コントローラでレンダリングしているHTMLテンプレート( error.exception )を示します。
/apricot/assets/views/error
{{-- 親レイアウト --}} @extends('error.layout') {{-- コンテンツ --}} @section('content') @php switch ($status_code) { case 400: $message = 'Bad Request'; break; case 401: $message = 'Unauthorized'; break; case 403: $message = 'Forbidden'; break; case 404: $message = 'Not Found'; break; case 405: $message = 'Method Not Allowed'; break; case 408: $message = 'Request Timeout'; break; case 414: $message = 'URI Too Long'; break; case 419: $message = 'Page Expired'; break; case 500: $message = 'Internal Server Error'; break; case 503: $message = 'Service Unavailable'; break; default: $message = 'Error'; break; } @endphp <div class="code">{{$status_code}}</div> <div class="message" style="padding: 10px;">{{ $message }}</div> @endsection
エラー画面を表示してみましょう。
.envを以下のように修正してデバッグモードから本番モードに変更します。
デバッグモードの時は集約エラーハンドラーは実行されません(その代わりに Whoops提供のPrettyErrorHandlerのデバッグ画面が表示されます )。
/apricot
... APP_DEBUG=false ...
ブラウザ上で以下のURLにアクセスしてみて下さい。
http://localhost/ws2019/apricot/public/users
次の画面が表示されます
テスト後は、.envを元に戻しておいて下さい。
... APP_DEBUG=true ...