こちらの記事は以下の書籍を参考に執筆しました
フィールドごとのエラー表示
テンプレをこのように修正する。
<p>{{$msg}}</p>
@if(count($errors)>0)
<p>入力に問題があり。再入力</p>
@endif
<form action="/hello" method="post">
<table>
@csrf
@if($errors->has('name'))
<tr><th>ERROR</th><td>{{$errors->first('name')}}</td></tr>
@endif
<tr><th>name:</th><td><input type="text" name="name" value="{{old('name')}}"></td></tr>
@if($errors->has('mail'))
<tr><th>ERROR</th><td>{{$errors->first('mail')}}</td></tr>
@endif
<tr><th>mail:</th><td><input type="text" name="mail" value="{{old('mail')}}"></td></tr>
@if($errors->has('age'))
<tr><th>ERROR</th><td>{{$errors->first('age')}}</td></tr>
@endif
<tr><th>age:</th><td><input type="text" name="age" value="{{old('age')}}"></td></tr>
<tr>
<th></th><td><input type="submit" value="send"></td>
</tr>
</table>
</form>
これでフィールドごとにエラーを表示できる。
firstでメッセージを取り出す
@if($errors->has('name'))
<tr><th>ERROR</th><td>{{$errors->first('name')}}</td></tr>
@endif
<tr><th>name:</th><td><input type="text" name="name" value="{{old('name')}}"></td></tr>
$ifディレクティブで$errors->has('name')
をチェックしている。
hasはエラーが発生しているかをチェックする。
$errors->has(項目名)
エラーが発生していれば$errro->first('name')
という値を出力しているがfirstは指定した項目最初のエラーメッセージを取得する。
$error->first(項目名)
これでname="name"のinputで発生したエラーが表示できる。
firstとget
firstは最初のエラーメッセージしか得られない
すべてのエラーメッセージを取得したい場合はgetを使う。
$変数=$error->get(項目名)
これ配列でまとめて返される。
以下はエラーメッセージを取得する3つのメソッド
名前 | 説明 |
---|---|
all | すべてのエラーメッセージを配列で取得 |
first | 指定した項目の最初のエラーメッセージを文字列で取得 |
get | 指定した項目のエラーメッセージをすべて取得 |
ここまでをまとめると
@ifで$error->hasのチェックをし、trueなら$error->firstや#error->getでエラーメッセージを取り出して表示する。
@errorディレクティブを使う
しかし上記の手順よりも簡単にバリテーションチェックとエラーメッセージを活用できるのが$errorディレクティブ
エラーメッセージの表示
# error(名前)
...$messageでメッセージを表示
@end$error
@errorディレクティブは()に指定した項目のエラーをチェックし、このディレクトティブ内に記述した内容を表示する。
このディレクティブでは発生したエラーメッセージが**\$message**という変数に渡される。
## 使ってみる。
```php5
<p>{{$msg}}</p>
@if(count($errors)>0)
<p>入力に問題があり。再入力</p>
@endif
<form action="/hello" method="post">
<table>
@csrf
@error('name')
<tr><th>ERROR</th><td>{{$message}}</td></tr>
@enderror
<tr><th>name:</th><td><input type="text" name="name" value="{{old('name')}}"></td></tr>
@error('mail')
<tr><th>ERROR</th><td>{{$message}}</td></tr>
@enderror
<tr><th>mail:</th><td><input type="text" name="mail" value="{{old('mail')}}"></td></tr>
@error('age')
<tr><th>ERROR</th><td>{{$message}}</td></tr>
@enderror
<tr><th>age:</th><td><input type="text" name="age" value="{{old('age')}}"></td></tr>
<tr>
<th></th><td><input type="submit" value="send"></td>
</tr>
</table>
</form>
$ifを#errornに書き換えただけ。これでさっきと同じようにエラーが表示される。
バリデーションをカスタマイズ
フォームリクエストとカスタムバリデーションでバリデーションをカスタマイズする。
フォームリクエストについて
validateメソッドはコントローラに処理を書く必要があり、入力値検証はホアに任せたい。そこでフォームリクエストが生まれた。
フォーム用拡張リクエスト
フォームリクエストはリクエストをフォーム利用のために拡張したもの。
LaravelehaクライアントからのリクエストはRequestクラスのインスタンスとして送られる。このRequestを継承して作成されたのがFromRequest。
これでフォームに関する機能をリクエストを組み込める。
送信されたフォームの内容をチェックするのはコントローラにあるよりもリクエストの内部で処理してくれる方がスマート。
フォームリクエストの作成
ではフォームリクエストを作成していく。
>出典:[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)
php artisan make:request HelloRequest
Http/Requestに作成される。
作成されたフォームリクエストはFormRequestを継承し、Requestを継承しリクエストの機能をベースにバリデーションなどのフォーム処理機能が追加されている。
FormRequestには以下の2つのメソッドが追加されている。
authorize
このフォームリクエストを利用するアクションでフォームリクエストの利用が許可されているかどうかを示す。戻り値がfalseならHttpExtentionという例外が発生してフォーム処理ができなくなる。
rules
適応されるバリデーションの検証ルールを設定する。
HelloRequestを修正する
public function authorize()
{
if($this->path()=='hello'){
return true;
}else {
return false;
}
}
public function rules()
{
return [
'name'=>'required',
'mail'=>'email',
'age'=>'numeric|between:0,150',
];
}
$this->path()でアクセスしたパスをチェックしている。
ここでhello以外は利用っできないようにしている。
バリデーションに関する部分をすべて消し、単にviewでテンプレとmsg変数を返すだけに修正する。
POST送信時のコントローラのアクションを修正する。
//use App\Http\Requests\HelloRequest;を追記する
public function post(HelloRequest $request){
return view('hello.index',['msg'=>'正しく入力された']);
}
ポイントは引数がRequestからHelloRequestに変わっていること
これでHelloRequestをの内容を元にバリデーションされる。
メッセージのカスタマイズ
もう少しカスタマイズしてみる。
これまでのエラーを日本語にしてみる。
FromRequestのmessageメソッドをオーバーライドする。
HelloRequestに追加する。
public function messages()
{
return [
'name.required'=>'名前は必須項目',
'mail.email'=>'メアドは必要',
'age.numeric'=>'整数で記入',
'age.between'=>'0から150で入力',
];
}
このmessageはFromRequestがバリデーション機能をエラーメッセージを必要とした時に呼びされるメソッド。配列でまとめられいて中身を見ると、
>出典:[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)
'name.required'=>'名前は必須項目',
**「'項目名.ルール名'=>'メッセージ'」**というメッセージ情報を記述する。
これはそれぞれのフィールドごとに用意した1つ1つのルールごとに用意する。
バリデータの作成
バリデーション機能ではFormRequestにあるvalidateメソッドを使って行われる。
validateはRequestインスタンスと検証ルールの引数を渡されることで自動的にフォームの値のチェックを行う、問題があればGETのページにリダイレクトしてフォームの再表示をする。
場合によってはエラーがあったらフォームページに行くのではなく、別の処理をさせたい場合もある。こういうときはバリデータを独自に用意して処理できる。
バリデータはバリデーションを行う機能のことでLaravelではValidatorというクラスがある。
コントローラーのvalidateメソッドを呼び出さず、このValidatorクラスのインスタンスを作成して処理することでバリデーションの処理をカスタマイズできる。
バリデータを使ってみる
バリデータは送信されたフォームを受け撮ったアクション内で作成する。
今回はpostメソッドに書いていく
//use Validator;を追加しておく
public function post(Request $request)
{
$validator=Validator::make($request->all(), [
'name'=>'required',
'mail'=>'email',
'age'=>'numeric|between:0,150',
]);
if ($validator->fails()) {
return redirect('/hello')->withErrors($validator)->withInput();
}
return view('hello.index', ['msg'=>'正しく入力された']);
}
/helloにアクセスステ確認してみると独自のバリデータでチェックが行われる。
バリデータ利用の基本
バリデータはValidatorインスタンスを作成するだけで使えるが、makeで作る必要がある。
$validator=Validator::make(値の配列,ルールの配列);
引数 | 説明 |
---|---|
第1引数 | チェックする値をまとめた配列。フォームをそのままチェックするなら$request->all()でOK |
第2引数 | 検証ルール情報を配列で。 |
エラーのチェックはこのように。
if ($validator->fails()) {...エラー時の処理...}
failsはバリデーションのチェックに失敗したかどうかを調べるもの。
戻り値がtureならエラーが発生している。
入力フォームへのリダイレクト
ここではエラー発生時にGETのページにリダイレクトしているが、振るうにリダイレクトしたらエラーメッセージやフォーム値が渡せない。そこでこのようにしている。
return redirect('/hello')
->withErrors($validator)
->withInput();
リダイレクトはredirectで行う。
指定のアドレスに移動させるだけならredirectだけでいい。
今回はエラーメッセージとフォーム入力情報をリダイレクトに追加している。
それがwithErrorsとwithInput
withErrors
引数にValidatorインスタンスを渡して、Validatorで発生したエラーメッセージをリダイレクト先まで引き継げる。
withInput
送信されたフォームの値をそのまま引き継げる。
クエリ文字列にバリデータを適用する
バリデータはフォーム以外のチェックにも使える。
例としてクエリ文字列で渡された値をチェックする。
コントローラのindexメソッドを修正する。
public function index(Request $request)
{
$validator=Validator::make($request->query(),[
'id'=>'required',
'pass'=>'required',
]);
if($validator->fails()){
$msg='クエリーに問題がある。';
}else {
$msg='ID/PASSを受け付けた。フォームを入力';
}
return view('hello.index', ['msg'=>$msg,]);
}
/hellにそのままアクセスするとモンぢがあると表示され/hello?id=xx&pass=xx
の形式で送信するとうまく表示される。
ここではValidator::makeメソッドの引数にkのような値を指定している。
$request->query()
これは送信されたクエリー文字列を配列形式でまとめたものを返す。
>出典:[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)
/hello?id=taro&pass=yamada
↓
['id'=>'taro','pass'=>'yamada']
第2引数ではこのように指定されている。
[
'id'=>'required',
'pass'=>'required',
]
検証ルールがまとめられている。
あとは$validator->fails()をチェックして表示するメッセージを設定するだけ。
「チェックする項目と値を連想配列にしてValidator::makeに渡す。」という長エレがわかればどんな値でもバリデーションでチェックができる。
エラーメッセージのカスタマズ
バリデータを利用する場合のエラーメッセージのカスタマイズはValidator::makeを呼び出す時に指定できる。
validator=Validator::make(値の配列,ルール配列,メッセージ配列);
第3引数にエラーメッセージ配列を用意する。これは先のエラーメッセージカスタマイズ時に使用したものと同じもの。
理解のためにPOST送信された時にメッセージ表示をしてみる。
public function post(Request $request)
{
$rules=[
'name'=>'required',
'mail'=>'email',
'age'=>'numeric|between:0,150',
];
$messages=[
'name.required'=>'名前は必須項目',
'mail.email'=>'メアドは必要',
'age.numeric'=>'整数で記入',
'age.between'=>'0から150で入力',
];
$validator=Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return redirect('/hello')
->withErrors($validator)
->withInput();
}
return view('hello.index', ['msg'=>'正しく入力された']);
}
これで日本語でエラーが表示される。
条件に応じてルールを追加する
必要に応じてルールを追加したい場合はValidatorクラスのsometimesというメソッドを使う
sometimes
処理を実行した結果によって新たにルールを追加できる。
$validator->sometimes(項目,ルール名,クロージャ);
クロージャはこのような形をしている。
function($input){
...処理を実行...
return 真偽値;
}
$inputには入力された値をまとめたものが渡される。
ここから**$input=>name**のように取り出せる。
戻り地は真偽値。
真偽値 | 説明 |
---|---|
true | 何もしない |
false | somerimesで指定したルールを指定の項目に追加 |
ルール追加をする。
コントローラのpostメソッドを優勢
public function post(Request $request)
{
$rules=[
'name'=>'required',
'mail'=>'email',
'age'=>'numeric',
];
$messages=[
'name.required'=>'名前は必須項目',
'mail.email'=>'メアドは必要',
'age.min'=>'0際以上で入力',
'age.max'=>'200歳以下で入力',
];
$validator=Validator::make($request->all(), $rules, $messages);
$validator->sometimes('age','min:0',function($input){
return !is_int($input->age);
});
$validator->sometimes('age','max:200',function($input){
return !is_int($input->age);
});
if ($validator->fails()) {
return redirect('/hello')
->withErrors($validator)
->withInput();
}
return view('hello.index', ['msg'=>'正しく入力された']);
}
今回は'age'=>'numeric'だけになっている。
minルールを見てみる
$validator->sometimes('age','min:0',function($input)
{
return !is_int($input->age);
});
クロージャで**!is_int($input->age)**の値を返している。
これにより$input->ageの値が整数の場合はfalseが返され、'min:0'のルールが'age'に追加される。