今回はLaravelの機能を使用して、フォームのバリデーションをする方法の記事になります。
コントローラに直接記述する方法で解説し、それをフォームリクエストを使用するように書き換えたバージョンも紹介できればと思います。
執筆時点でLaravelのバージョンは7.6になります。
今回バリデーションしてみる内容
今回は以下のようなユーザ情報登録用のフォームを想定して見たいと思います。
<form method="POST" action="/action">
{{ csrf_field() }}
名前:<input type="text" name="name"><br>
メール:<input type="text" name="email"><br>
年齢:<input type="text" name="age"><br>
<input type="submit" value="送信">
</form>
コントローラーでバリデーション
先程作成したフォームの送信先のコントローラを作成します。コントローラ作成にはartisanコマンドが便利ですね。
$ php artisan make:controller UserController
するとコントローラができますので、登録用のstoreメソッドを作成します。
ここで、デフォルトでuseしてあるIlluminate\Http\Requestクラスをメソッドの引数に与えます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
// 処理
}
}
これで準備は完了したので、バリデーション本体を記述していきます。
バリデーションを行うには$request->validate()を呼び出します。
書き方は以下の通りです。
// array $rules : バリデーションルール
// array $messages : メッセージ(省略可)
// array $attributes : メッセージ中のアトリビュートの指定(省略可)
$request->validate($rules, $messages, $attributes);
実際にどう適用すればいいのかといいますと、以下のようにしてみましょう。
class UserController extends Controller
{
public function store(Request $request)
{
$request->validate([
'name' => 'required', // requiredというルールを適用
'email' => 'required|email', // required, emailを適用
'age' => 'integer|between:0,100', // integer, between:0,100を適用
]);
}
}
このようにフォームのname属性の値に適用したいルールを記述するだけで勝手にバリデーションしてくれます。
ここで出てきたルールは以下のとおりです。
ルール | 説明 |
---|---|
required | 必須項目 |
メールアドレス形式であるか | |
integer | 整数形式であるか |
between:0,100 | 0から100の間か |
これら以外にもたくさんのバリデーションルールがありますので、一度公式マニュアルに目を通してみることをおすすめします。
この$request->validate()に成功した場合には処理を続行し、失敗した場合には元のページにエラーメッセージ付きでリダイレクトします。
エラーメッセージの表示
ではどうやってエラーメッセージを表示するのかといいますと、エラーメッセージは$errors変数に格納されていますので、これを使用します。
// すべて出力
@foreach ($errors->all() as $error)
{{ $error }}
@endforeach
// 最初の1つだけ出力
{{ $errors->first() }}
エラーメッセージの編集
次にエラーメッセージの編集方法を2通り紹介します。
言語ファイルを編集する方法
共通のエラーメッセージは「resources/lang/〇〇/validation.php」を編集することで、設定します。
〇〇の部分は日本語ならja, 英語ならenといった具合です。
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
*/
// ルールごとの共通メッセージ
'required' => ':attribute は必須です',
'email' => ':attribute はメールアドレス形式である必要があります。',
'integer' => ':attribute は整数形式である必要があります。',
'between' => ':attribute は :min から :max の間である必要があります。',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
*/
// ageのbetweenルールのときのメッセージ
'custom' => [
'age' => [
'between' => ':attribute は :min 歳から :max 歳の間である必要があります。',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
*/
// :attribute のところに当てはめる文字
'attributes' => [
'name' => '名前',
'email' => 'メール',
'age' => '年齢',
],
$request->validate()に直接記述する方法
共通のものではなくそのページ独自のメッセージを使用したい場合もあると思います。
なので他の方法として、$request->validate()の第2引数と第3引数を使用して編集することもできます。
$request->validate([
'name' => 'required',
'email' => 'required|email',
'age' => 'integer|between:0,100',
],
[
'required' => ':attribute は必須です。',
'email' => ':attribute はメールアドレス形式である必要があります。',
'integer' => ':attribute は整数形式である必要があります。',
'age.between' => ':attribute は :min 歳から :max 歳の間である必要があります。',
],
[
'name' => '名前',
'email' => 'メール',
'age' => '年齢',
]);
フォームに送信前の値を残す
ここまでで、バリデーション、メッセージの表示とやってきましたが、あと一つやっておきたいことがあります。
それはフォーム送信後、バリデーションエラーになった際にフォームの入力値がクリアされてしまうことです。
それを防ぐためにLaravelではセッションに古いフォームデータが保存されています。これはoldというヘルパー関数で取り出せます。
// $name : フォームのname属性
// $default : デフォルトの値(省略可)
old($name, $default)
これをフォームのvalue属性にセットして置くことで、より良いフォームになったと言えます。
<form method="POST" action="/action">
{{ csrf_field() }}
名前:<input type="text" name="name" value="{{ old('name') }}"><br>
メール:<input type="text" name="email" value="{{ old('email') }}"><br>
年齢:<input type="text" name="age" value="{{ old('age') }}"><br>
<input type="submit" value="送信">
</form>
さてここまでで、コントローラを使用したバリデーションの一連の作成方法でした。
最後にコントローラから分離してバリデーションする方法を書いておきます。コントローラの肥大化が防げるので個人的におすすめです。
フォームリクエストを使用する方法
まずは、バリデーションをするためにFormRequestを継承したクラスを作成します。
これもartisanコマンドで簡単に作成できます。
php artisan make:request UserStoreRequest
すると以下のようなファイルがapp/Http/Requests配下に作成されています。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
ここに必要なメソッドを追加していきます。
これの$rulesをrulesメソッドの返り値に、$messagesをmessagesメソッドの返り値に、$attributesをattributesメソッドの返り値にすればよいのです。
先程の例を用いると以下のようにします。(コメントは省略してます)
class UserStoreRequest extends FormRequest
{
public function authorize()
{
return true; // 注:trueに変える
}
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email',
'age' => 'integer|between:0,100',
];
}
public function messages()
{
return [
'required' => ':attribute は必須です。',
'email' => ':attribute はメールアドレス形式である必要があります。',
'integer' => ':attribute は整数形式である必要があります。',
'age.between' => ':attribute は :min 歳から :max 歳の間である必要があります。',
];
}
public function attributes()
{
return [
'name' => '名前',
'email' => 'メール',
'age' => '年齢',
];
}
}
「resources/lang/〇〇/validation.php」の共通設定を使用する場合はmessages()とattributes()は不要です。
また、コントローラを修正します。
デフォルトでIlluminate\Http\Requestを使用しているので、App\Http\Requests\UserStoreRequestに変更しておきます。
// Illuminate\Http\Requestから変更
use App\Http\Requests\UserStoreRequest;
class UserController extends Controller
{
// 引数をRequestからUserStoreRequestに変更
public function store(UserStoreRequest $request)
{
// バリデーションは記載の必要なし
// 処理
}
}
これでフォームリクエストを使用した場合にもバリデーションを導入できました。
コントローラもスッキリしていいですね。
最後に
バリデーションはいかがだったでしょうか。
バリデーションって実装しようとすると、いろんなパターンを考慮しなくてはいけなくて大変だったりするのですが、それもLaravelを使えば簡単にできてしまいます。