はじめに
Laravel9から12へ移行した際に、app/Exceptions/Handler.php の例外処理の書き方が変わっていたため、備忘録として残します。
また、Laravel11以降は bootstrap/app.phpに記載するように変更されています。
Laravel10以前の書き方
- ファイル:
app/Exceptions/Handler.php - カスタマイズは
report() / render()をオーバーライド -
register()内でreportable() / renderable()を登録する
app/Exceptions/Handler.php
class Handler extends ExceptionHandler
{
public function register(): void
{
$this->reportable(function (Throwable $e) {
// ログ・Sentry通知など
});
$this->renderable(function (ModelNotFoundException $e, $request) {
return response()->view('errors.404', [], 404);
});
}
}
Laravel12の書き方
- ファイル:
bootstrap/app.phpのwithExceptions() - クロージャベースで記述するスタイルに変更
bootstrap/app.php
use Illuminate\Foundation\Configuration\Exceptions;
return Application::configure(basePath: dirname(__DIR__))
->withExceptions(function (Exceptions $exceptions) {
// ログ出力
$exceptions->report(function (Throwable $e) {
// Slack通知やSentry送信
});
// レンダリング
$exceptions->render(function (ModelNotFoundException $e, $request) {
return response()->json([
'message' => 'Resource not found',
], 404);
});
})
->create();
-
withExceptionsの中を見てみる - ハンドラをシングルトンで登録し、解決されたタイミングで
withExceptionsの設定を適用するフックを登録しているみたい
vendor/laravel/framework/src/Illuminate/Foundation/Configuration/ApplicationBuilder.php
/**
* Register and configure the application's exception handler.
*
* @param callable|null $using
* @return $this
*/
public function withExceptions(?callable $using = null)
{
$this->app->singleton(
\Illuminate\Contracts\Debug\ExceptionHandler::class,
\Illuminate\Foundation\Exceptions\Handler::class
);
$using ??= fn () => true;
$this->app->afterResolving(
\Illuminate\Foundation\Exceptions\Handler::class,
fn ($handler) => $using(new Exceptions($handler)),
);
return $this;
}
- Laravel9では
app->singleton部分は、ここにあるみたい
vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
まとめ
- Handler.php に書くスタイルに慣れていたので、bootstrap/app.php に例外処理を書くのはまだ違和感があります。
最近の Laravel は、ミドルウェアやイベント設定なども含めて bootstrap/app.php に集約される傾向があるので、このファイルが肥大化しやうい印象です。