Laravel

【Laravel】バリデーションの作成

簡単な掲示板アプリケーションを作成するつもりでバリデーションを学習してみたいと思います。

【1】 基本のバリデーションを作成する

以下のような構成を想定しています。

Boardの仕様
・投稿のタイトル (subject)、
・メールアドレス(email)、
・本文 (message) をフィールドに持っており、タイトルと本文は必須。

タイトルは 10文字、本文は 50 文字の制限をつける。
テストなので、文字数制限は少なめにしています。

BoardController:Board モデルを操作するためのコントローラー。
以下のアクションを設定

・indexアクション:ユーザーが投稿作成を行うページ。
・addアクション:投稿データを送信する先。
・投稿内容をバリデートし、問題なければ index ページにリダイレクト、間違っていれば index ページに戻しエラーを表示する。

ひとまず、バリデーションが通っても通らなくても index ページを表示させるものを作成して、肉付けしていきます。
テンプレートは以前の「星・月・太陽ページ」で作成したものを流用します。

ルーティング

\routes\web.php に以下を追記。

以前にも思いましたが、POSTアクセス、GETアクセス両方を書くのが正しいのかが、やっぱりまだわかりません。
なんとなく違和感がありますね。

コントローラー

\app\Http\Controllers\BoardController.php は以下のようにします。

indexページには『投稿内容を入力してください』というメッセージを設定(表示)し、入力が問題なく行われた場合に『正しく入力されました!』というメッセージが表示されるようにしています。

addアクションの

にて、ルールの設定を行い、

が、バリデーションを実行している部分となります。

ひとつの項目に複数のルールを設定したい場合はパイプ記号「|」にて連結することで設定可能。
subject(件名)に対してはrequired(必須)とmax:10(上限10文字)を設定しています。

ビュー

\resources\views\board\index.blade.php

star.blade.php をコピーして書き換えています。

画面表示

フォーム3つにデータを入力して「送信」ボタンをクリックします。

上部に表示されているメセージが『投稿内容を入力してください』から『正しく入力されました!』になりましたが、ただそれだけです。
試しに再度フォーム画面を表示して、何も入力せずに「送信」ボタンをクリックしてみますと、ページ遷移も何もしません。

今のところは仕様通りの動きをしていますが、これでは何もわからないですし使い物になりませんが、徐々に理解を深めていきたいと思います。

【2】 エラーメッセージと値の保持

先程作成した基本形のバリデーションへ肉付けを行っていき、使えるものとしていきたいと思います。
以下の2点に関して、機能追加したいと思います。

1. エラーメッセージの表示(何がどう悪いのかを投稿者に伝える)
2. 再入力の際には、先に入力した内容をセットしておく(項目が100個あるフォームがすべてクリアされたりすると確実に誰も投稿しないw)

ビューの修正

まずは、エラーがある場合はその旨のメッセージをフォーム上部にまとめて表示させてみます。
indexの @section('content') を以下のように編集します。

(結果)画面表示

各フォームの要件を満たさないようにデータ入力して「送信」ボタンをクリックします。
すると、、、

1. なにやら英語のメッセージが表示された
2. 入力した内容もそのまま表示された

と、上で挙げた、1、2にうまく対応できました。

なお、メッセージは上から、

「件名」は必須です
「メールアドレス」はemailの形式で入力してください
「メッセージ」は50文字以内で入力してください

となり、想定通り(仕様通り)のメッセージとなっていますね。

エラーメッセージ、送信内容を表示する仕組み

エラーメッセージ

エラーメッセージの表示処理は結構単純ですね。
if文で、 $errors という配列(オブジェクト?)をcount関数で判定しているだけです。

$errors に関しては、バリデーションが自動的に作成してくれる便利機能のようで、開発者が値に関して設定やらをする必要はなく、結果をまとめて作成してくれるとのこと。
素晴らしい。

$errors の内容はどうなっているのかを確認すると、以下のようになっていました。
(ビューの)if文の前に 簡単にデバッグができる魔法の言葉 {{ dump($errors) }} を書きます。

デバッグされましたが、(慣れていないので)よくわからんw
単純に var_dump() した内容も載っけておきます。

それぞれの項目に対応するエラー内容のメッセージがセットされています。
なるほどですね。

配列化されているので、 foreach でぐるぐる回して表示しているだけです。
bladeテンプレートでの foreachになっているので少し注意です。

送信内容

送信内容に関しては、単純に各フォームの value に値を設定するという方法で実現しています。
old() というメソッドを使用しているだけ。
old()メソッドは、引数に指定した入力項目の古い値(現在の値が設定される前の値)を返すという便利関数。
コントローラーでの作業は一切せず、ビューファイルへの記述だけで処理を行ってくれます。便利!

ひとまずここまで。
と思いましたがせっかくなので、項目ごとのエラーメッセージの取得方法も追加します。

【3】バリデーションエラーを項目ごとに表示する

ビュー

まとめて表示するのが出来ましたので、次は項目ごとに表示させてみたいと思います。
先と同じように、index.blade.php の @section('content') を以下のように編集します。

各項目の上にテーブルタグを含んだ if文を挟み、firstメソッドでエラーメッセージを取り出して表示している構成です。
この状態でフォームに何も入力せずに送信ボタンを押すと、以下のようになります。

↑ 指定箇所に、エラーメッセージが表示されました

hasメソッド / firstメソッド

@ifディレクティブで $errors->has('subject') としていますが、この has はエラーが発生しているかをチェックするメソッドで、以下のように指定して実行できます。

firstメソッドは指定した項目の最初のエラーメッセージを取得するものです。
以下のようにして利用します。

これでエラーメッセージが取得できます。
今回の場合だと、$errors->first('subject') で件名フォームの「最初の」エラーが取得可能です。
「最初の」とわざわざカッコ書きしているのには理由があり、検証ルールが複数設定されている場合で、例えば2つのエラーが発生した場合でも「最初のエラーメッセージのみ」が取得されます。

getメソッド

1つの項目(フォーム)に検証ルールを複数設定し、発生した全てのエラーメッセージを取得したい場合は、getメソッドを利用すれば取得可能です。
getメソッドは以下のようにして利用します。

引数には取得したい項目名を指定します。

戻り値にはその項目で発生した全てのエラーメッセージが配列でまとめられます。配列で返るので、変数化する、foreachで順次表示する、などのように使用することが可能です。

-Laravel
-