Laravel 8.x エラー処理

イントロダクション

エラーと例外の処理は、新しいLaravelプロジェクトの開始時に最初から設定されています。App\Exceptions\Handlerクラスは、アプリケーションが投げるすべての例外がログに記録され、ユーザーへレンダーする場所です。このドキュメント全体を通して、このクラスについて詳しく説明します。

設定

config/app.php設定ファイルのdebugオプションは、エラーに関する情報が実際にユーザーに表示される量を決定します。デフォルトでは、このオプションは、.envファイルに保存されているAPP_DEBUG環境変数の値を尊重するように設定されています。

ローカル開発中は、APP_DEBUG環境変数をtrueに設定する必要があります。実稼働環境では、この値は常にfalseである必要があります。本番環境で値がtrueに設定されていると、機密性の高い設定値がアプリケーションのエンドユーザーに公開されるリスクが起きます。

例外ハンドラ

例外のレポート

すべての例外は、App\Exceptions\Handlerクラスが処理します。このクラスは、カスタム例外レポートとレンダリングコールバックを登録できるregisterメソッドを持っています。こうした各概念について詳しく説明します。例外レポートは、例外をログに記録したり、FlareBugsnagSentryなどの外部サービスへ送信したりするために使用します。デフォルトで例外はログ設定に基づいてログに記録します。ただし、必要に応じて例外を自由に記録できます。

たとえば、さまざまなタイプの例外をさまざまな方法で報告する必要がある場合は、reportableメソッドを使用して、特定のタイプの例外を報告する必要があるときに実行するクロージャを登録できます。Laravelは、クロージャのタイプヒントを調べることで、クロージャが報告する例外のタイプを推測します。

use App\Exceptions\InvalidOrderException;

/**
 * アプリケーションの例外処理コールバックを登録
 *
 * @return void
 */
public function register()
{
    $this->reportable(function (InvalidOrderException $e) {
        //
    });
}

reportableメソッドを使用してカスタム例外レポートコールバックを登録した場合でも、Laravelはアプリケーションのデフォルトのログ設定を使用して例外をログに記録します。デフォルトのログスタックへ例外の伝播を停止する場合は、レポートコールバックを定義するときにstopメソッドを使用するか、コールバックからfalseを返します。

$this->reportable(function (InvalidOrderException $e) {
    //
})->stop();

$this->reportable(function (InvalidOrderException $e) {
    return false;
});

Tip!! 特定の例外のレポートをカスタマイズするには、レポート可能な例外を利用することもできます。

グローバルログコンテキスト

利用可能な場合、Laravelは現在のユーザーのIDをコンテキストデータとしてすべての例外のログメッセージに自動的に追加します。アプリケーションのApp\Exceptions\Handlerクラスのcontextメソッドをオーバーライドすることで、独自のグローバルコンテキストデータを定義できます。この情報は、アプリケーションによって書き込まれるすべての例外のログメッセージに含まれます。

/**
 * ログ用のデフォルトのコンテキスト変数を取得
 *
 * @return array
 */
protected function context()
{
    return array_merge(parent::context(), [
        'foo' => 'bar',
    ]);
}

例外ログコンテキスト

すべてのログメッセージにコンテキストを追加することは便利ですが、特定の例外にはログに含めたい固有のコンテキストがある場合もあります。アプリケーションのカスタム例外にcontextメソッドを定義することで、例外のログエントリに追加すべき、その例外に関連するデータを指定することができます。

<?php

namespace App\Exceptions;

use Exception;

class InvalidOrderException extends Exception
{
    // ...

    /**
     * 例外のコンテキスト情報を取得
     *
     * @return array
     */
    public function context()
    {
        return ['order_id' => $this->orderId];
    }
}

reportヘルパ

場合により、例外を報告する必要はあるが、現在のリクエストの処理を続行する必要がある場合もあります。reportヘルパ関数を使用すると、エラーページをユーザーに表示せずに、例外ハンドラを介して例外をすばやく報告できます。

public function isValid($value)
{
    try {
        // 値のバリデーション…
    } catch (Throwable $e) {
        report($e);

        return false;
    }
}

タイプによる例外の無視

アプリケーションを構築するときに、単に無視するだけで報告したくないタイプの例外もいくつかあるでしょう。アプリケーションの例外ハンドラには、空の配列に初期化されている$dontReportプロパティが含まれています。このプロパティに追加したクラスは報告されません。ただし、カスタムレンダリングロジックがある場合もあります。

use App\Exceptions\InvalidOrderException;

/**
 * 報告しない例外タイプのリスト
 *
 * @var array
 */
protected $dontReport = [
    InvalidOrderException::class,
];

Tip!! Laravelは、404 HTTP "not found"エラーや無効なCSRFトークンによって生成された419 HTTPレスポンスに起因する例外など、いくつかのタイプのエラーを皆さんのために裏でこっそり無視しています。

例外のレンダー

デフォルトでは、Laravel例外ハンドラは例外をHTTPレスポンスへ変換します。ただし、特定タイプの例外に対して、カスタムレンダリングクロージャを自由に登録できます。これは、例外ハンドラのrenderableメソッドを介して実行します。

renderableメソッドへ渡すクロージャは、Responseヘルパを介して生成されるIlluminate\Http\Responseのインスタンスを返す必要があります。Laravelは、クロージャのタイプヒントを調べることで、どのタイプの例外をクロージャがレンダーするのか推測します。

use App\Exceptions\InvalidOrderException;

/**
 * アプリケーションの例外処理コールバックを登録
 *
 * @return void
 */
public function register()
{
    $this->renderable(function (InvalidOrderException $e, $request) {
        return response()->view('errors.invalid-order', [], 500);
    });
}

また、renderableメソッドを使い、NotFoundHttpExceptionなどのLaravelやSymfonyの組み込み例外のレンダー動作をオーバーライドすることもできます。renderableメソッドに指定したクロージャが値を返さない場合は、Laravelのデフォルト例外レンダーが利用されます。

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * アプリケーションの例外処理コールバックの登録
 *
 * @return void
 */
public function register()
{
    $this->renderable(function (NotFoundHttpException $e, $request) {
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'Record not found.'
            ], 404);
        }
    });
}

Reportable/Renderable例外

例外ハンドラのregisterメソッドで例外を型チェックする代わりに、カスタム例外に直接reportメソッドとrenderメソッドを定義することもできます。これらのメソッドが存在する場合、フレームワークによって自動的に呼び出されます。

<?php

namespace App\Exceptions;

use Exception;

class InvalidOrderException extends Exception
{
    /**
     * 例外を報告
     *
     * @return bool|null
     */
    public function report()
    {
        //
    }

    /**
     * 例外をHTTPレスポンスへレンダリング
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function render($request)
    {
        return response(...);
    }
}

LaravelやSymfonyの組み込み済み例外など、既存のレンダリング可能な例外を拡張している場合は、例外のrenderメソッドからfalseを返し、例外のデフォルトHTTPレスポンスをレンダーできます。

/**
 * Render the exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function render($request)
{
    // 例外がカスタムレンダリングを必要とするか判定…

    return false;
}

特定の条件が満たされた場合にのみ必要なカスタムレポートロジックが例外に含まれている場合は、デフォルトの例外処理設定を使用して例外をレポートするようにLaravelに指示する必要が起き得ます。これを行うには、例外のreportメソッドからfalseを返します。

/**
 * 例外を報告
 *
 * @return bool|null
 */
public function report()
{
    // 例外にカスタムレポートが必要かどうかを判定…

    return false;
}

Tip!! reportメソッドで必要な依存関係をタイプヒントすると、Laravelのサービスコンテナがメソッドへ自動的に依存を注入します。

HTTP例外

一部の例外は、サーバからのHTTPエラーコードを表します。たとえば、「ページが見つかりません」エラー(404)、「不正なエラー」(401)、または開発者が500エラーを生成する可能性もあります。アプリケーションのどこからでもこのようなレスポンスを生成したい場合は、abortヘルパを使用できます。

abort(404);

カスタムHTTPエラーページ

Laravelを使用すると、さまざまなHTTPステータスコードのカスタムエラーページを簡単に表示できます。たとえば、404 HTTPステータスコードのエラーページをカスタマイズする場合は、resources/views/errors/404.blade.phpビューテンプレートを作成します。このビューは、アプリケーションが生成するすべての404エラーでレンダーされます。このディレクトリ内のビューには、対応するHTTPステータスコードと一致する名前を付ける必要があります。abort関数によって生成されたSymfony\Component\HttpKernel\Exception\HttpExceptionインスタンスは$exception変数としてビューに渡されます。

<h2>{{ $exception->getMessage() }}</h2>

vendor:publish Artisanコマンドを使用して、Laravelのデフォルトのエラーページテンプレートをリソース公開できます。テンプレートをリソース公開したら、好みに合わせてカスタマイズしてください。

php artisan vendor:publish --tag=laravel-errors

ドキュメント章別ページ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる