プロミディア合同会社の斉藤です。
今回はPHP Laravelを使って、バリデーションを実装する方法を解説します。
バリデーションは、ほとんどのWebアプリケーションで使われる機能ですので、この記事を読んで理解を深めてください。
記事内ではバリデーションの部分だけ解説するので、全ソースが欲しい方はGitHubに上げたソースコードをご覧ください。
完成イメージ
Laravelでバリデーションを実装するための概要
Laravelではフォームリクエストという機能を使ってバリデーションを実装します。
厳密にはフォームリクエストを使わずに、コントローラ内に記述することもできるのですが、それだとコントローラ内に処理とバリデーションが混在してしまい、可読性が悪くなります。
ですので、基本的にバリデーションはフォームリクエストを使うものであると覚えておきましょう。
また、バリデーションの代表的なチェックパターンはフレームワーク側で用意されているので、普通のチェックであれば簡単に実装できます。
今回使用するバリデーションのチェックパターン
今回のサンプルプログラムでは、よくありそうなチェックを入れてみました。
- 未入力
- メールアドレス
- 数値の範囲指定
- 文字数制限
- ラジオボタンでの必須撰択
- 英語以外の文字が含まれている
用意されているバリデーションの全パターンについては、下記の公式サイトを参照してください。
フォームリクエストでバリデーションが実行されるタイミング
コントローラの引数に通常のリクエストではなく、作成したバリデーションのリクエストを指定するとコントローラに入ってくる前にバリデーションが実行されるようになります。
詳しくは後ほど出てくるソースコードをご覧ください。
フォームリクエストを使うメリット
- バリデーションの実装だけをコントローラから分離できる
- 日本語で独自のエラーメッセージを表示することができる
バリデーションの実装
今回のサンプルプログラムでは、単純に1画面だけの入力フォームで解説していきます。
各項目のバリデーション内容がわかるように、ラベルに書いておきました。
※Formファサード、Bootstrapを使用していますが、その部分の解説は省略しています。
ルーティング
ルートは下記の2つのみです。
routes/web.php
1 2 |
Route::get('/', 'ValidateTestController@index'); Route::post('/', 'ValidateTestController@create'); |
バリデーションする側のみメソッドの引数の型を変えるので、メソッドはgetとpostで別にする必要があります。(最初、一緒のメソッドにしてハマりました)
フォームリクエストの作成
プロジェクトフォルダ直下でターミナルから下記コマンドを実行して、バリデーション用のクラスを作成します。
php artisan make:request ValidateTestRequest
※リクエストの名前は任意でつけてください。今回は「ValidateTestRequest」という名称にしています。
フォームリクエストの実装
初期状態から
- authorize
- rules
- messages
を今回の仕様に合うように書き換えます。
app/Http/Requests/ValidateTestRequest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class ValidateTestRequest extends FormRequest { public function authorize() { if ($this->path() === '/') { //リクエストのパスが"/"のときだけ、このクラスで定義した //バリデーションルールを適用する return true; } else { return false; } } public function rules() { return [ 'text1' => 'required', 'text2' => 'email', 'text3' => 'numeric|between:0,100', 'text4' => 'size:5', 'radio1' => 'required', 'text6' => 'alpha', ]; } public function messages() { return [ 'text1.required' => '必須入力です。', 'text2.email' => 'メールアドレスの形式ではありません。', 'text3.numeric' => '1〜100の範囲で入力してください。', 'text4.size' => '5文字以内で入力してください。', 'radio1.required' => 'いずれかを撰択してください。', 'text6.alpha' => '英語以外の文字が含まれています。', ]; } } |
※text1などは各コントロールのid値です。
エラーメッセージを日本語で表示させる
エラーメッセージを日本語で表示させるには、FormRequestのmessagesメソッドをオーバーライドします。
書き方については上記のrulesとmessagesの対応を見ていただけたらわかるかなと思います。
コントローラの実装
createメソッドの引数の型をValidateTestRequestに変更することで、POSTのときのみバリデーションが行われるようになります。
app/Http/Controllers/ValidateTestController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; //作成したバリデーションを使用する use App\Http\Requests\ValidateTestRequest; class ValidateTestController extends Controller { public function index(Request $request) { return view('create'); } public function create(ValidateTestRequest $request) { return view('create'); } } |
ビューの実装
ビューでは、エラーがあったときだけ、エラーメッセージを表示する実装とするのがポイントです。
resources/views/create.blade.php
※フォーム部分のみ抜粋
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<!-- 登録フォーム --> {!! Form::open() !!} <div class="col-4"> <div class="form-group"> <div> {!! Form::label('label1', '必須入力') !!} {!! Form::text('text1', null, ['class' => 'form-control']) !!} @if ($errors->has('text1')) <p class='error-string'>{{ $errors->first('text1') }}</p> @endif </div> {!! Form::label('label2', 'メールアドレス') !!} {!! Form::text('text2', null, ['class' => 'form-control']) !!} @if ($errors->has('text2')) <p class='error-string'>{{ $errors->first('text2') }}</p> @endif {!! Form::label('label3', '数値(1〜100)') !!} {!! Form::text('text3', null, ['class' => 'form-control']) !!} @if ($errors->has('text3')) <p class='error-string'>{{ $errors->first('text3') }}</p> @endif {!! Form::label('label4', '文字数制限(5文字以内)') !!} {!! Form::text('text4', null, ['class' => 'form-control']) !!} @if ($errors->has('text4')) <p class='error-string'>{{ $errors->first('text4') }}</p> @endif {!! Form::label('label5', '必須選択') !!} <div class="radio"> <label>{!! Form::radio('radio1', '1') !!} 男性</label> <label>{!! Form::radio('radio1', '2') !!} 女性</label> </div> @if ($errors->has('radio1')) <p class='error-string'>{{ $errors->first('radio1') }}</p> @endif {!! Form::label('label6', '英語のみ') !!} {!! Form::text('text6', null, ['class' => 'form-control']) !!} @if ($errors->has('text6')) <p class='error-string'>{{ $errors->first('text6') }}</p> @endif </div> {!! Form::submit('登録', ['class' => 'btn btn-primary btn-block']) !!} </div> {!! Form::close() !!} |
$errors->hasでその項目にエラーがあるかチェックし、あるのであれば、$errors->firstで最初の1件を取り出しています。
今回は使いませんが、全部のエラーを取り出したければ$errors->allを使用します。
@if ($errors->has(‘text1′))
<p class=’error-string’>{{ $errors->first(‘text1’) }}</p>
@endif
ダウンロード
今回解説したサンプルプログラムをGitHubにアップロードしました。
https://github.com/SadayoshiSaito/validate_sample