laravel12.laravel_100
R e i - D r e a m
for Laravel
TOP > Laravel Ver.12 > その他中間モジュール
Guest
login

最終投稿日:2026年3月15日

【検証環境】- Laravel Ver.12 - Windows11 - Rocky Linux Ver.8 - MySQL Ver.8 - MySQL Ver.9
目次
○ エラーハンドリング
[エラーを制御する事はとっても大事]
多言語化
[Laravelはアメリカ生まれなので日本語は苦手?]
メール送信
[Yahooメールを送信してみよう]
ファイル操作
[Lravelのクラスを利用して簡単ファイル操作]
エラーハンドリング
エラー操作の重要性
システム構築において、エラーとの付き合い方は非常に大事です。
たまに頭の悪い上流の人間が、
『テストケースが増えるから意識的な[throw]は不要』
『わざわざ処理が止まるコードは書かないでね』
などのIT関連の思考とは思えない事を言いますが。。
声を大にして言いたい。
意図しない動きをシステムがしたときは即座に停止させろっ!! です。
例えばある処理をしている際に、本来は必ず取得できるレコードが取得できなかった場合どうしますか?
この状態で後続の処理が実行され、運良く(悪く?)システムが落ちずに正常終了したとします。
これ本当に正常終了ですかね?
あなたの知らない所、例えば「請求書の金額」とか「発注書の数量」に影響しているかも知れません。
システムは正常終了しているので誰も気づきませんが、請求書はゼロ円なので発行はされない。
発注書は逆に不要な品物まで納品している可能性もあります。
そして数ヵ月後、「最近入金が少ないなぁ」「倉庫に余計な物多くない?」と、徐々に明るみになり、
ようやくシステム障害が発生している事に気がつくのです。
しかも処理自体は正常終了しているため、何処に原因があるかが即座には判断がつきません。
こうなると組織としては疑心暗鬼ですよね。
果たして障害の影響は「請求書」「発注書」だけなのか?と、当然なります。
つまり原因が解明できるまで、最悪システムの停止となり数億単位の損害になる可能性もあります。
対して例外を[throw]していた場合はどうでしょう。
処理が止まりログに原因を記述している事で『秒』で障害発生から原因の特定までできます。
これであれば被害は最小限に抑えられますよね。
システムはどんなに堅牢でセキュアなフレームワークを使っても、設計思想においては当然人間が担います。
それなのに『テスト面倒くさい』『本番で処理止まったら信用がぁ』などの後ろ向き思考や、
顧客からの要望を右から左に伝えるだけの小学生でもできる伝言ゲーマー。
こんな人間がIT部門の上流にいる組織は不憫でなりません。
何処からかデスマーチという名の足音が聞こえてきませんか?
独自のエラークラスを作成する
それでは独自クラス『MyException』クラスを作成してみましょう。
作成する場所は「~\app\Exceptions\MyException.php」とします。
MyException.php

<?php
namespace App\Exceptions;
use Exception;
class MyException extends Exception {
    // コンストラクタ
    public function __construct($error = []) {
        $this->code = $error['code'] ?? 0;
        parent::__construct($error['message'] ?? '内部エラーが発生しました。');
    }
}

次に同ディレクトリにエラーを制御するハンドラー『ExceptionHandler』クラスを作成します。
ExceptionHandler.php

<?php
namespace App\Exceptions;
use Illuminate\Foundation\Configuration\Exceptions;
class ExceptionHandler {
    public static function handle(Exceptions $exceptions) {
        $exceptions->renderable(function (\Throwable $e, $request) {
            // エラー種別判定
            var_dump("OK");

        });
    }
}

それでは作成した「ExceptionHandler」クラスをシステムに登録します。
~\bootstrap\app.php

use App\Exceptions\ExceptionHandler;
~ 省略 ~
    ->withExceptions(function (Exceptions $exceptions): void {

        ExceptionHandler::handle($exceptions);
    })->create();

それでは動作確認してみましょう。
まずは任意のコントローラに以下コードを記述してエラーにしてみましょう。
    $hoge = 10/0;
どうでしたか?『string(2) "OK" 』と表示されましたか?
もしLaravelのエラー画面が表示された場合は、PHPのバージョンが[7]以下となります。
期待通りの場合は[Ver.8]以降となります。
次に以下のコードでエラーにしてみましょう。
use App\Exceptions\MyException;
~ 省略 ~
    throw new MyException(['code'=>'aaa', 'message'=>'bbb']);
こちらは仮に[PHP Ver.7]でも期待通りに『string(2) "OK"』とでるハズです。
メモ

エラークラスの基底となるクラスは『Throwable』となります。
この基底クラスから『Exception』『Error』クラスの2種類が枝分かれしています。
[PHP Ver.8]は両方のクラスを例外として[throw]しますが、[PHP Ver.7]は「Exception」のみを[throw]します。
先ほどのコード【$hoge=1/0;】のエラーは「Error」クラス起因ですので補足できないのです。
また「Throwable」であれば[PHP Ver.7]でも補足はできるのですが、このバージョンでのゼロ除算の扱いは「Warning」扱いのため【例外】ですらありません。

ExceptionHandlerの詳細設定
それでは途中だった『ExceptionHandler』クラスの続きを作成しましょう。
ExceptionHandler.php

<?php
namespace App\Exceptions;
use Illuminate\Foundation\Configuration\Exceptions;

use App\Exceptions\MyException;
use Illuminate\Validation\ValidationException;
class ExceptionHandler {
    public static function handle(Exceptions $exceptions) {

        $exceptions->renderable(function (\Throwable $e, $request) {
            $errors = [
                'code' => $e->getCode(),
                'path' => $e->getFile(),
                'line' => $e->getLine(),
            ];
            // バリデーションエラーは除外
            if ($e instanceof ValidationException) {
                return;
            }
            // エラー種別判定
            if ($e instanceof MyException) {
                $errors['title'] = 'MyException';
                $errors['message'] = $e->getMessage();
            } else {
                $errors['title'] = $e->getMessage();
                $errors['message'] = '内部エラーが発生しました。';
            }
            return response()->view("errors.500", ['errors'=> $errors]);
        });
    }
}

最後にエラー画面を作成します。 『~\resources\views\errors\500.blade.php』へ作成します。
500.blade.php

<!DOCTYPE HTML>
    <HEAD>
        <TITLE>SeverError</TITLE>
        <link rel="stylesheet" href="{{ asset('css/base_css.css') }}" />
    </HEAD>
    <BODY>
        {{ $errors['title'] }}
        <BR />
        {{ $errors['message'] }}
        <BR />
        {{ $errors['code'] }}
        <BR />
        {{ $errors['path'] }}
        <BR />
        {{ $errors['line'] }}
    </BODY>
</HTML>

制御内容を軽く説明すると、通常PHPの例外であれば以下の内容は自動的に格納されています。
$e->getCode()
$e->getFile()
$e->getLine()
$e->getMessage()
独自例外『MyException』の場合は、以下をスロー時に付与する事で同様の内容を格納する事ができます。
throw new MyException(['code'=>'aaa', 'message'=>'bbb']);
変数をセット後に『~\resources\views\errors\500.blade.php』をレンダリングします。
ポイント

[500.blade.php]は、実はLaravelが500エラーを感知した際に自動的にレンダリングされるファイルでもあります。
今回はエラーハンドリングをしているため意識手にレンダリングしていますが、
例えば「~\errors\404.blade.php」なんてのもあります。
試しに作成して存在しないURLを叩いてみて下さい。
 ※ただしエラーハンドリングをしている場合は、今回の設定通り500エラーとなります。

また『.env』にて『APP_DEBUG=false』とすると、バリデーションエラーもここにハンドリングされるため除外しています。

ログインしてコメントを残そう!!


きっぷる