ValidationRuleとFormRequestについて

Validationは検証と訳されます。ValidationRuleとは検証における規則ということです。 Laravelはある程度の基本的なバリデーションルールを備えており、組み合わせて使うこともできます。

また、バリデーションの処理自体はコントローラーに直接書くこともできますがファットになり可読性が落ちることもあります。そこでFormRequestクラスを利用します。FormRequestクラスはバリデーションルールを定義するためのクラスなので管理しやすくなります。

準備

まずはFormRequestクラスを継承したクラスをartisanコマンドで作成します。実行すると、app\Http\Requestディレクトリに設置されます。ディレクトリがない場合は作成されます。以下はコマンドの雛形です。

$ php artisan make:request <クラス名>

今回は公式ドキュメントと同じクラス名にします。クラス名はStoreBlogPostです。記事投稿する時のバリデーションですね。このクラスにルールを定義していくことになります。

また、バリデーションルールの実行はコントローラーで行うので、PostControllerというクラス名でコントローラーも作成しましょう。以下のコマンドを実行します。

$ php artisan make:controller PostController

次にvalidation.blade.phpというフォームのビューを用意します。タイトルと本文があり、投稿ボタンで投稿ができるフォームです。ただし、投稿の処理はありません。

最後に、ルートを定義します。先ほど作成したフォーム画面を表示するルートとバリデーションを行うルートの2つを用意します。

こんな感じの入力画面ができると思います。

フォームの入力画面

バリデーションルールの定義

作成直後のStoreBlogPost.phpの中身は2つのメソッドが書かれています。authorize()とrules()です。authorize()は権限の確認です。記事の更新をしようとする人がその記事を作成した本人なのかどうか、などの確認です。認可の必要がないけどバリデーションの必要がある場合は、trueを返せば大丈夫です。falseの場合はステータスコードが403のHTTPレスポンスが返されます。今回は単純にtrueを返すようにします。

rules()はそのままの意味で、バリデーションルールを定義します。 キーにバリデーションの対象(要素のname属性)、バリューにルールを指定します。今回はtitleとbodyの要素にrequired(必須)というルールを設定します。

バリデーションルールの実行

定義したバリデーションルールを実行しましょう。作成しておいたコントローラーに2つのメソッドを書きます。

create()はフォームを表示するためのメソッドです。ただビューを返しているだけです。store()は本来であればフォームで入力された値をデータベースなどに登録する処理を書くメソッドですが、今回はバリデーションについてなのでその処理は省略します。

このうち、store()の引数にさきほど作成したStoreBlogPostクラスをタイプヒントで指定するだけで実行されます。

バリデーションを行いたいメソッドの引数にタイプヒントで指定することがポイントです。また、バリデーションに失敗するとコントローラーのメソッドの処理が行われずに直前の画面にリダイレクトされるようになっています。

以下は成功した時の画面です。

フォームの入力画面

エラーの表示

バリデーションが失敗すれば直前の画面に戻ります。この時にエラーがあれば表示する必要があります。バリデーションエラーは全て$errorsという変数に格納されることになっています。これは

App\Http\kernel.php
のwebでまとめられたミドルウェアの
\Illuminate\View\Middleware\ShareErrorsFromSession
で行なっています。ちなみに$errorsは
Illuminate\Support\MessageBag
のインスタンスなので、エラーメッセージの扱いはここを見るといいです。

エラーをリストで表示する時は以下のような条件分岐にします。表示の際はall()というエラーの配列を返すメソッドをforeachでループさせます。

それと、全エラーをリストで表示しても具体的にどこのエラーなのかわかりづらいので、ラベルの近くでエラーを表示させたほうがいいこともあります。その際、入力した値を入力済みの状態にするとユーザビリティが向上します。

ポイントはfirst()です。このメソッドは第1引数で指定した文字に対応したエラーメッセージを返します。引数で指定するのはinput要素などのname属性です。今回のように、タイトルのエラーメッセージを表示したい場合は引数にtitleを、本文のエラーメッセージならbodyを指定します。また、第1引数を指定しなかった場合は、バリデーションに失敗した全要素のエラーメッセージのうち最初の1つを返します。

また入力した値はセッションに自動で入るようになっています。これを取得するためにold()を使います。引数はfirst()と同様に、要素のname属性を指定しましょう。

そして、エラーを表示した画面はこうなります。

エラーメッセージの表示

日本語化

さて、ここまでバリデーションのロジックは終わりました。ただ、通常のエラーメッセージは英語です。Laravelは多言語に対応できるようになっていますので日本語のエラーメッセージにしましょう。

多言語の対応はresources\langディレクトリで行います。デフォルトではenディレクトリがありますが、これをコピーしてjaというディレクトリを作ります。

エラーメッセージに関するファイルはvalidation.phpになりますので、これを日本語の記述に直せばいいわけです。このファイルは連想配列を返すだけのファイルです。キーがルール、バリューがエラーメッセージです。

エラーメッセージに:attributeがありますが、これはプレースホルダーなので触らないようにしましょう。この:attributeはフォームの要素のname属性に置き換わるようになっていますが、ここも日本語になるようにします。

まずはStoreBlogPostクラスにattributes()を追加します。このメソッドはFormRequestクラスのメソッドでオーバーライドすることで日本語にできます。

エラーメッセージを日本語にしていきましょう。長いので省略しますが、requiredというキーを見つけて以下のように書き換えましょう。

最後に、config\app.phpのlocaleに先ほど作ったjaディレクトリを指定します。日本語されたエラーメッセージを表示させましょう。

日本語化したエラーメッセージの表示

これで、エラーメッセージも日本語になりました。手っ取り早く日本語に書き直したファイルが欲しい場合はララ帳のエラーメッセージファイルにを参照してください。

まとめ

以上が簡単なFormRequestの使い方でした。いかがでしたか。

僕はよほど簡単なバリデーションルールじゃない限りFormRequestを使うようにしています。簡単でファイルがまとまってすっきりするので。

コントローラーに直接書くにせよ、バリデーションは必ずと言ってもいいほど必要な処理になります。これを簡単に実装できるLaravelはやはり素晴らしいですね。