[Laravel] 値検査(バリデーション)について

福岡拠点の野田です。
秋雨や台風が気になりますが、過ごしやすい日々が増えてきたと思います。
今日は、Laravel の値検査の仕組みについて取り上げようと思います。

Laravel には値検査を行う設計の方向性として大きく3つの選択肢があります。
・FormRequest を継承してリクエストフォームオブジェクトを作る
・ValidatesRequestsトレイトを使う
・Validator ファサードを使う

FormRequestを作る場合

Controller に対して Illuminate\Foundation\Http\FormRequest 型のメソッドインジェクションを指定しておくとそのメソッドに対応するURLが呼び出された際に値検査がかかるという仕組みになります。バリデーションの結果が false の場合、リクエスト値をセッションに保存して、リクエストを投げた前のページに戻ります。

とても便利な仕組みですが、都度、FormRequestを実装することになります。毎回似たようなコードを書くのは煩わしいですよね。そこで以下のような基底クラスを作成して継承して使いまわすことにします。この基底クラスは、自分のクラス名からバリデーションの設定を読み込んで動作する仕組みで動いています。

以下は、config/validation.php の記述例です。FormRequest実装クラス名をキーに設定を記述するとそれを読み込んでくれる仕掛けになっています。クラスの型を利用しつつ、リクエスト値の検査は設定ファイルを利用してカスタマイズしやすくします。

さらにテンプレート側に目を向けてみましょう。入力フォームのテンプレートは、エラー表示と「戻る」ボタンで遷移の両方を共通で実現している場合がほとんどだと思います。Laravel で用意されている old ヘルパーメソッドで取得できるのは、エラー時のセッションしかありませんので、以下のような記述をすることでエラー時のセッション値があれば、セッション値、なければリクエスト値をとる実装が可能です(old メソッドのデフォルト値にリクエスト値を設定する実装になります)。

エラーを表示する場合は以下で対応できます。

$errors->has(’email’)や$errors->count()などもよく使うメソッドだと思います。エラーは MessageBag というクラスで定義されていますので、以下を参考にしていただければ幸いです。

https://laravel.com/api/5.6/Illuminate/Support/MessageBag.html

ValidatesRequestsトレイトを使う場合

FormRequest の処理のうち Controller 側の処理を切り出したものが ValidatesRequest になります。
Controller で use ValidatesRequest をすることで Controller 中で $this->validate() メソッドなどが使えるようになります。

以下 Laravel マニュアルページより

値検査に失敗すると Illuminate\Contracts\Validation\ValidationException が発生し、FormRequest 同様、前のページに戻ります。validateをかけるタイミングを調整できるため、リクエスト値の前処理が必要な場面や FormRequest の作成をしたくない場合に使われると思いますが、Validator ファサードの選択肢もあるため、相対的に利用する場面は少ないと思われます。

Validatorファサードを使う場合

Validator ファサードを使えば値検査部分だけを部品化して値検査をすることが可能です。バッチ系で値検査を行うときは直に呼び出して使うことが多いと思います。例えばCSVインポートバッチの入力値チェックなどはこの Validatorファサードの出番です。

上記は、config/validation.php で設定を外だししている例です。個別実装することももちろん可能ですが、ある程度共通化できるところは共通化しておくと良いでしょう。

まとめ

なんだかんだいいましたが、場面場面に応じて最適な値検査の方法を選択して実装していくとよいでしょう。その中で特に伝えたかったことが「設定ファイル化」という部分になります。値検査(バリデーション)というプログラムの課題の中でconfig/validation.php にまとめておく、HTML部品という課題の中で config/form.php にまとめておく、アプリケーション設定として、config/const.php にまとめておく、などなどです。後で入力チェックをまとめるときに個別の実装をみなくてよいのは、大きな助けになると思います。まだの方は、実装時の良い習慣としてプログラムの課題の設定ファイル化を是非やってみてください。

補足

以下補足になります。入力、確認、完了のような遷移がある場合のルーティングのTIPSです。通常、入力画面は、GETリクエスト、それ以外はPOSTリクエストとしていると思います。つい忘れがちですが、保存ページについては、GETも受け付けて入力画面に逃がすとよいと思います。戻すときの遷移でリロードして、MethodNotAllowedのエラーが見えてしまうとちょっとカッコ悪いですよね。