【Laravel】 Requestを継承してバリデーションをする
リクエストで入ってきた値は、その値が正常な値かどうかをチェックするのが普通です。Laravelでは、楽にバリデーションを行える機構が存在しています。
目次
バリデーションする
Controllerでバリデーションする場合、$request->validate([/* ... */])
を用います。
バリデーションルールは連想配列で指定し、キーに入力欄名を、値にルールを配列か|
区切りの文字列で並べます。
public function postData(Request $request) { $request->validate([ 'title' => ['required', 'between:4,64'], 'content' => ['required'], ]); // ... }
$request->validate([ 'title' => 'required|between:4,64', 'content' => 'required', ]);
ルール一覧はLaravelのドキュメントを参照してください。https://readouble.com/laravel/9.x/ja/validation.html#available-validation-rules
バリデーションルールはかなり数が多いため、よく使用するものだけ載せておきます。
名前 | 役割 |
---|---|
required | 必須項目 |
min max between:min,max | 入力の長さや数値の範囲等。between はbetween:4,64 のように書く |
email | 文字列がemailの形式かどうか |
date | 日付かどうか+日付として正しいかどうか |
だいたいこれで事足りると思います。
条件付きでバリデーション
その項目がフォームに存在する場合のみチェックする、特定の項目が存在すればチェックしないなど、条件付きでバリデーションを行うことができます。
$request->validate([ // bailは、失敗したもの以降をチェックしないもの。下の例では、alpha_dashに失敗したらbetweenはチェックしない 'title' => 'bail|required|alpha_dash|between:4,64', 'content' => 'required' // sometimesは、フィールド自体がなければチェックしない 'num' => 'sometimes|integer|between:1,100', 'is_share' => 'required|boolean', // is_shareがfalseの場合は飛ばす (excludeする) 'share_range' => 'exclude_if:is_share,false|required', ]);
バリデーションをカスタマイズ
デフォルトで用意されているバリデーションでは対応できないような場合、ルールを配列で並べ、その中に関数を含めます。
関数内では第1引数に入力欄のnameが、第2引数のその入力欄の値、第3引数には失敗時に呼び出すための関数が入ります。
この関数内で他の値を参照したい場合、普段どおり$request->get('name');
のようにします。(関数でuse
するのを忘れないようにする)
$request->validate([ 'content' => ['required', function ($name, $item, $fail) use(&$request) { Log::debug($name); // 'content' Log::debug($item); // 入力した値 // useすると$request->input等で他の入力値も参照できる Log::debug($request->input($name)); if (strpos($item, '<script>') !== false) { // バリデーションに引っ掛ける場合は $fail('メッセージ') を呼び出す $fail('本文にscriptタグを含めることはできません'); } }], ]);
バリデーションのエラー表示
バリデーションに引っかかると、Laraveは自動的に文章を生成します。生成した文章は、blade側で$errors
に格納されます。
@if ($errors->any()) <!-- 何らかのエラーがあるかどうか --> <div class="alert alert-danger"> <ul> <!-- 全てのエラーをforeachで出力 --> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif
これらのバリデーションエラーで表示されるメッセージは、app/lang/en/validation.php
に入っています。
FormRequestを拡張する
Controllerにバリデーションを書いても良いですが、複雑になると収集がつかなくなります。また、バリデーションを使い回せません。
そこで、FormRequest
クラスを継承したクラスを作りましょう。
php artisan make:request SamplePostRequest
これを実行すると、app/Http/Requests
ディレクトリ内にファイルが作成されます。
バリデーションのルール
rules
の戻り値の連想配列は、Controllerでvalidate
を使用した時と同様にキーに入力欄名、値にバリデーションルールを記載します。複数のルールがある場合、それらを|
で区切るか、配列で書きます。
public function rules() { return [ 'title' => 'required|between:4,64', 'num' => 'required|integer|between:1,100', 'content' => 'required' ]; }
public function rules() { return [ 'title' => ['required', 'between:4,64'], 'num' => ['required', 'integer', 'between:1,100'], 'content' => ['required'], ]; }
バリデーションをカスタマイズ
基本的にはコントローラでした場合と同じですが、他の値を参照したい場合、$this->request->get('name');
のようにします。
public function rules() { return [ 'content' => ['required', function ($name, $item, $fail) { Log::debug($name); // 'content' Log::debug($item); // 入力した値 // $this->request->get で他の入力値も参照できる Log::debug($this->request->get($name)); if (strpos($item, '<script>') !== false) { // バリデーションに引っ掛ける場合は $fail('メッセージ') を呼び出す $fail('本文にscriptタグを含めることはできません'); } }], ]; }
バリデーションのメッセージ
バリデーションで引っかかった場合の表示をカスタマイズできます。
新たにmessages
メソッドを作成し、その戻り値に連想配列を用意します。
連想配列には、'入力名.バリデーションルール' => '表示メッセージ'
のように書きます。ここにはないバリデーションエラーの場合、デフォルトのメッセージが使用されます。
public function rules() { return [ 'title' => 'required|between:4,64', 'num' => 'required|integer|between:1,100', 'content' => 'required' ]; } public function messages() { return [ 'title.required' => 'タイトルは必須です', 'title.between' => '文字数は4~64文字に設定してください', 'num.between' => '数値は1~100に設定してください', ]; }
バリデーション失敗時のリダイレクト先
デフォルトでは元いたページに戻されます。もし別のページに移動させたい場合は、$redirect
に代入します。
// バリデーション失敗時の移動先 protected $redirect = '/home';
// ルート名を利用した移動 protected $redirectRoute = 'form.error'; // Route::get('/err', [/*...*/])->name('form.error');
// コントローラを利用した移動 protected $redirectAction = 'App\Http\Controllers\HelloController@err';
リクエストの承認機能
リクエストを投げたユーザが、そのリクエストの使用を承認されているかをauthorize
メソッドで判定できます。何かややこしいことをするわけでもなく、true
を返せば認可、false
を返せば不認可ということになります。
public function authorize() { // 常に認可する return true; }
public function authorize() { $isLoggedIn = false; try { // ... } catch ( Exception $ex ) { // ... return false; } return $isLoggedIn; }
入力された値を復元する
バリデーションに失敗して元のページに戻ると、入力が消えていることがあります。ブラウザが復元してくれればよいですが、復元できるとは限りません。
そこで、old('name')
を用いて復元できます。
<label> title: <input type="text" name="title" value="{{ old('title') }}"> </label> <label> content: <textarea name="content" cols="10" rows="5">{{ old('content') }}</textarea> </label>
バリデーションでは自動で保存されますが、それ以外でセッションに入力を一時保持したい場合、内部で$request->flash()
すると可能です。$request->flashOnly(['title', 'content'])
やflashExcept('password')
のように、flash対象を選ぶこともできます。
まとめ
フォームリクエストを処理する際にバリデーションは必要不可欠です。バリデーションの共通化をするには、できるだけFormRequest
を継承したクラスに書くと、Controllerの肥大化を防ぐことができます。
関数をバリデーションルールに入れることで複雑なバリデーションもコントローラに入れずに済みます。