Laravelのバリデーションエラーと通常の例外の違いを理解しよう!初心者向け完全ガイド
生徒
「Laravelでエラーを調べていたら『バリデーションエラー』と『例外』という言葉が出てきました。これって同じものですか?」
先生
「似ているようで、実は役割が全然違います。それぞれの意味と使い方をしっかり区別して覚えておくと、エラー処理がグッと楽になりますよ。」
生徒
「具体的にどう違うんですか?」
先生
「実際のコードを見ながら説明しましょう。イメージをつかむための例えも用意しましたよ!」
1. バリデーションエラーとは何か?基本を知ろう
Laravelでフォームからデータを受け取るとき、そのデータが正しい形かどうかをチェックする処理をバリデーションといいます。日本語では「入力検証」とも呼ばれます。
たとえばユーザー登録フォームで「メールアドレスを入力してください」という欄があったとします。そこに「abcdef」という文字が入力された場合、それはメールアドレスの形式ではありません。このようにルールに合わない入力があったときに発生するのがバリデーションエラーです。
身近なものに例えると、銀行のATMに暗証番号を入力するときのようなイメージです。数字4桁でなければならないのに文字を入力しようとすると「入力できません」と弾かれる、あの仕組みがバリデーションに近いものです。ユーザーが間違った情報を入力したことを知らせるためのものなので、バリデーションエラーはいわば「ユーザー向けのお知らせ」といえます。
2. 通常の例外(Exception)とは何か?
一方、例外(Exception)とは、プログラムが動いている途中で予期しない出来事が起きたときに発生するエラーのことです。バリデーションエラーがユーザーの入力ミスに関するものであるのに対して、通常の例外はシステムや開発者側の問題で起きることが多いです。
例えば「データベースへの接続が突然切れた」「存在するはずのファイルが見つからなかった」「外部のAPIサービスが応答しなかった」といった状況が例外にあたります。これらはユーザーが何か操作を間違えたわけではなく、システム側で想定外のことが起きた状態です。
先ほどの銀行ATMの例えで続けると、暗証番号は正しく入力したのにATM自体が故障して動かなくなった、という状況が例外に近いイメージです。ユーザーには責任がなく、システム側で何か問題が起きているという点が大きな違いです。
Laravelでは例外が発生するとapp/Exceptions/Handler.phpがその例外を受け取って処理します。このファイルを編集することで、例外が起きたときの動作をカスタマイズできます。
3. バリデーションの基本的な書き方
Laravelのバリデーションは、コントローラー(処理を担当するファイル)の中でRequestオブジェクトのvalidate()メソッドを使って書くのが一般的です。メソッドとは、クラスの中に定義された処理のまとまりのことです。
以下はユーザー登録時の入力チェックをバリデーションで行う例です。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
// バリデーションのルールを定義する
$request->validate([
'name' => 'required|max:50', // 必須・最大50文字
'email' => 'required|email', // 必須・メール形式
'age' => 'required|integer|min:18', // 必須・整数・18以上
]);
// バリデーションを通過した場合のみここに処理が来る
return response()->json(['message' => '登録が完了しました。']);
}
}
バリデーションのルールはパイプ(|)で区切って複数指定できます。requiredは必須入力、emailはメール形式であること、max:50は最大50文字までという意味です。バリデーションに失敗すると、Laravelは自動的にValidationExceptionという例外を発生させてエラーメッセージをユーザーに返します。
4. ValidationExceptionが発生したときの動作の違い
バリデーションが失敗したときにLaravelが自動で発生させるValidationExceptionは、通常の例外と比べて特殊な動作をします。
通常のWebページへのアクセスの場合、バリデーションエラーが起きると自動的にひとつ前のページにリダイレクト(転送)され、入力フォームのそばにエラーメッセージが表示されます。一方、APIへのアクセスの場合はJSON形式でエラー内容が返されます。この切り替えをLaravelが自動で判断してくれるのはとても便利な仕組みです。
エラーメッセージをbladeテンプレート(Laravelの画面表示用ファイル)で表示するには以下のように書きます。
<!-- resources/views/users/create.blade.php -->
<form method="POST" action="/users">
@csrf
<input type="text" name="name">
<!-- nameフィールドのエラーメッセージを表示 -->
@error('name')
<div class="text-danger">{{ $message }}</div>
@enderror
<button type="submit">登録する</button>
</form>
@error('フィールド名')はそのフィールドにバリデーションエラーがあるときだけ中の内容を表示するLaravel独自の書き方です。{{ $message }}はエラーメッセージの内容を画面に出力します。このようにValidationExceptionはフォームとの連携が非常にスムーズになるよう設計されています。
5. 通常の例外を自分でキャッチして処理する方法
バリデーションエラーはLaravelが自動で処理してくれますが、通常の例外は場合によって自分でキャッチして対処する必要があります。キャッチとは例外を受け取って処理することを意味します。
PHPではtry-catchという構文を使って例外を手動でキャッチできます。tryブロックの中に「失敗する可能性がある処理」を書き、catchブロックに「失敗したときの対処」を書きます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Exception;
class FileController extends Controller
{
public function show()
{
try {
// 失敗する可能性がある処理(ファイルの読み込み)
$content = file_get_contents('/path/to/file.txt');
return response()->json(['content' => $content]);
} catch (Exception $e) {
// 例外が起きたときの処理
return response()->json([
'status' => 'error',
'message' => 'ファイルの読み込みに失敗しました。',
], 500);
}
}
}
file_get_contents()はファイルの内容を読み込む関数ですが、ファイルが存在しないなどの理由で失敗することがあります。try-catchを使うと、失敗してもプログラムが止まらず、catchブロックに書いた代替の処理が動きます。バリデーションエラーと違い、こういった予期せぬエラーは自分で対処の仕方を考えて書く必要があるのが通常の例外の特徴です。
6. バリデーションエラーと例外の主な違いを整理しよう
ここまでの内容を踏まえて、バリデーションエラーと通常の例外の主な違いを整理しておきましょう。
まず発生原因の違いです。バリデーションエラーはユーザーの入力内容がルールに合わないときに発生します。通常の例外はシステムや外部環境の問題など、プログラムが予期しない状況になったときに発生します。
次に対象者の違いです。バリデーションエラーは「ユーザーへのお知らせ」です。入力を直してもらうための情報をわかりやすく伝えることが目的です。通常の例外は主に開発者やシステム管理者向けの情報です。ログに記録したり、運営側に通知したりすることが多いです。
またLaravelの自動処理にも違いがあります。ValidationExceptionはLaravelが自動で前のページへのリダイレクトやJSONレスポンスへの変換をしてくれます。通常の例外はHandler.phpに処理を書かなければ、デフォルトのエラー画面が表示されるだけです。
この違いを理解しておくと、どちらのエラーが起きているのかを素早く判断でき、適切な対処ができるようになります。開発中に「エラーが出た」と焦ったときも、まず「これはユーザーの入力ミスか、それともシステム側の問題か」を考えることが原因特定への近道になります。
7. FormRequestを使ったバリデーションの分離
コントローラーにバリデーションをそのまま書く方法はシンプルですが、チェックするルールが増えてくるとコードが長くなって読みにくくなってしまいます。そういったときに便利なのがFormRequestクラスです。
FormRequestとは、バリデーションのルールをコントローラーから切り離して専用のクラスに書く仕組みです。以下のArtisanコマンドで作成できます。
// ターミナルで実行するコマンド
php artisan make:request StoreUserRequest
このコマンドを実行するとapp/Http/Requests/StoreUserRequest.phpというファイルが生成されます。このファイルのrules()メソッドにバリデーションのルールをまとめて書き、コントローラーの引数の型をRequestからStoreUserRequestに変えるだけで自動的にバリデーションが実行されます。
FormRequestを使うことでコントローラーはデータの処理だけに集中できるようになり、コード全体がすっきりと整理されます。バリデーションルールを後から変更したいときも、FormRequestのファイルだけを修正すればよいので管理がとても楽になります。コードを書く量が増えてきたら、ぜひFormRequestの活用を検討してみてください。