見出し画像

Laravel 学習記録 #016 例外処理を試して学ぶ

Laravelの例外処理について学習したものをまとめてます。

例外処理はエラーハンドリングは標準機能として
App\Exceptions\Handlerクラスがやってくれています。

このあたりをいじれば色々できそうです。
今回は以下の2点について試してみました。
・例外発生時にログテーブルへ記録する
・例外発生時に独自で作成したビューを表示させる

例外発生時にログテーブルへ記録する

準備として、テーブル、モデルを作成します。

エラーログテーブルを作成

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('error_logs', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id')->nullable();
            $table->string('user_name')->nullable();
            $table->string('controller');
            $table->string('action');
            $table->boolean('error_flag');
            $table->text('message');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('error_logs');
    }
};

合わせてモデルを作成

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ErrorLog extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'user_name',
        'controller',
        'action',
        'error_flag',
        'message',
    ];
}


では、本題のログテーブルへの登録をします。
登録内容はユーザー情報やコントローラー名、アクション名、メッセージなどです。
Handlerクラスのregisterメソッドに追加します。

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use App\Models\ErrorLog; // 追加
use Illuminate\Support\Facades\Auth; // 追加

class Handler extends ExceptionHandler
{
    

    /**
     * Register the exception handling callbacks for the application.
     */
    public function register(): void
    {
        $this->reportable(function (Throwable $e) {

            // 登録内容
            $userId         = null;
            $userName       = null;
            // ログイン済みの場合ユーザー情報追加
            if(Auth::check()) {
                $user       = Auth::user();
                $userId     = $user->id;
                $userName   = $user->name;
            }
            $controller     = class_basename(request()->route()->getController());
            $action         = request()->route()->getActionMethod();
            $errorFlag      = true;
            $message        = $e->getMessage();

            
            // ログをデータベースに保存
            ErrorLog::create([
                'user_id'       => $userId,
                'user_name'     => $userName,
                'controller'    => $controller,
                'action'        => $action,
                'error_flag'    => $errorFlag,
                'message'       => $message,
            ]);
        });
    }
    
}

これで、例外発生時にDBへ登録する処理が準備できました。
コントローラーでExceptionをスローしてみます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Auth; // 追加

class ExceptionController extends Controller
{

    public function index()
    {
        // 仮ログイン
        Auth::login(User::find(1));

        // 例外スロー
        throw new \Exception('例外エラーをDB登録');
        
        return view('exception');
    }
}

これでアクセスすると例外エラーが発生します。
これで無事に登録できているか、ErrorLogモデルを取得してます。

  "id" => 1
  "user_id" => 1
  "user_name" => "ユーザー1"
  "controller" => "ExceptionController"
  "action" => "index"
  "error_flag" => 1
  "message" => "例外エラーをDB登録"
  "created_at" => "2023-12-30 05:08:33"
  "updated_at" => "2023-12-30 05:08:33"

問題なく登録されているようです。
これで例外発生時にログテーブルへの登録はできました。


例外発生時に独自で作成したビューを表示させる

これもよくある処理ですね。
LaravelではHTTPステータスコードのカスタムエラーページを簡単に作成できます。
resources/views/errors/[ステータスコード].blade.php
という命名のファイルを用意するだけです。

サーバーエラー用に500.blade.phpを作成します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>エラー</title>
</head>
<body>
    <h1>Error:500</h1>
    <p>システムエラーが発生しました。</p>
    <p>時間を空けてから再度お試しいただくか、システム管理者にお問い合わせください。</p>
</body>
</html>

デバッグモードがオンになっているとLaravelのエラーページが表示されるのでオフにして確認が必要です。

// .envファイル

APP_DEBUG=false

これで先程と同様の確認をすると、上記作成ページが表示されます。

いや、全部のステータスコード作成めんどいな
例外発生時は全部同じ画面でいいんだよなって場合は
Handlerクラスにrenderメソッドに定義でいいんですかね。

以下のファイルを作成して、例外発生時に表示します。
resources/views/errors/fallback.blade.php


public function render($request, Throwable $exception)
    {
        return response()->view('errors.fallback');
    }

これで例外発生時にエラーページを表示できました。


まだまだ、実務で使う際には気をつけるべき点が結構ありそうですね。
例外処理はプロジェクトごとに方針異なることが多々あるので、そこに合わせてやっていきましょう。

この記事が気に入ったらサポートをしてみませんか?