目次

Apricot エラー画面

y2sunlight 2020-05-09

Apricot に戻る

関連記事

アプリのエラー画面を作ります。
エラー画面は集約例外ハンドラー(Whoops)から呼び出されます。


エラー画面の設定

エラー画面を表示するアクションメソッドは通常の(リクエストルータ経由の)アクションとは異なり、集約例外ハンドラーから呼び出されます。このアクションメソッドの設定は以下の設定ファイルで行います。 これは既に各種コアクラス集約エラーハンドラの項で説明済ですが、念のため以下に再掲しておきます。

設定ファイル

/apricot/config/setting

whoops.setting.php
<?php
return
[
    'debug' => env('APP_DEBUG',false),
    'controller' => \App\Exceptions\UncaughtExceptionHandler::class,
    'action' => 'render',
];


集約例外コントローラ

集約例外ハンドラーから呼び出されるコントローラを集約例外コントローラと呼びます。whoops.setting.php での設定に従い UncaughtExceptionHandler@render メソッドが実行されてエラー画面を表示します。以下に集約例外コントローラを示します。

/apricot/app/Exceptions

UncaughtExceptionHandler.php
<?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);
    }
}


HTMLテンプレート

エラー画面のレイアウトは以下の2つのHTMLテンプレートから成っています。

テンプレート error.exception は、error.layout から継承して作成します。

error.layout

以下にエラー画面共通のレイアウト( error.layout )を示します。CSSやJavaScriptも使用せずに出来るだけシンプルなHTMLになっています。

/apricot/assets/views/error

layout.blade.php
<!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>

error.exception

以下に集約例外コントローラでレンダリングしているHTMLテンプレート( error.exception )を示します。

/apricot/assets/views/error

exception.blade.php
{{-- 親レイアウト --}}
@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

.env
...
APP_DEBUG=false
...

ブラウザ上で以下のURLにアクセスしてみて下さい。

http://localhost/ws2019/apricot/public/users

次の画面が表示されます


テスト後は、.envを元に戻しておいて下さい。

.env
...
APP_DEBUG=true
...