Laravelでバリデーションエラーが発生した際、それを表示させるのはviewの役目です。そのうち最も一般的と思われるのが、デフォルトで採用されるbladeです。
本ページでは、そんなbladeを使用して、エラーメッセージを表示させる方法を具体例を交えてご紹介します。
実際のWebアプリケーションでもエラーの見せ方は避けては通れません。本ページではこんなこともできるよ!という例をいろいろと改造しながらやっていきます。
具体例ではなく、マニュアル的に読みたい方は本ページではなく、以下ページをご覧ください。
前提条件
法人のお問い合せフォームなどによくある条件で、簡素な例としてイメージしました。
バリデーション設定
FormRequest
を継承した、InquiryRequest
にてバリデーションを設定しています。正直、この辺はLaravel初心者さんは分からなくてもOK。
なぜならこのページの焦点となるのは、エラーの表示だからです(最悪、分からなくても良いです)。
namespace App\Http\Requests\Contact;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
class InquiryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* バリデーションルールを定義
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|max:20',
'furigana' => 'max:20',
'tel' => 'nullable|regex:/^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$/',
'email' => 'required|email',
'body' => 'required|max:1000',
'is_accepted' => 'accepted',
];
}
/**
* バリデーションエラーメッセージを定義
*
* @return array
*/
public function messages(): array
{
return [
'name.required' => ':attributeは必須項目です。',
'name.max' => ':attributeは最大:max文字以内で入力してください。',
'furigana.max' => ':attributeは最大:max文字以内で入力してください。',
'tel.regex' => ':attributeはハイフンをいれた数字でご入力ください。',
'email.required' => ':attributeは必須項目です。',
'email.email' => ':attributeを正しく入力してください。',
'body.required' => ':attributeは必須項目です。',
'body.max' => ':attributeは最大:max文字以内で入力してください。',
'is_accepted.accepted' => ':attributeにチェックをつけてください。',
];
}
/**
* カスタム属性名を定義
*
* @return array
*/
public function attributes(): array
{
return [
'name' => 'お名前',
'furigana' => 'ふりがな',
'tel' => '電話番号',
'email' => 'Email',
'body' => 'お問い合せ内容',
'is_accepted' => 'ご利用規約に同意する',
];
}
}
名前などの各項目に、最低限のバリデーションルールが設定されているとお考えください。
標準的なエラーを表示する
コード
あえてシンプルなview(blade)にしました。いろいろあると逆に分かりづらいので、お名前以外は省略しています。
<form action="{{ url('/contact/inquiry') }}" method="post">
@csrf
<dl class="form">
<div class="form-item">
<dt>お名前
<span class="form-required">必須</span>
</dt>
<dd>
<input type="text" name="name" class="form-input" value="{{ old('name') }}">
@error('name')
<div class="error"><span>{{ $message }}</span></div>
@enderror
</dd>
</div>
<!-- ~省略~ -->
</dl>
<div>
<button type="submit">送信する</button>
</div>
</form>
実際のエラー画面
先ほどのコードでのエラー時のスクリーンショットです。フォーム項目のすぐ下にエラーを表示しているのがわかります(簡単にCSSで色を分かりやすくしています)。
コード解説
もう少しコードをクローズアップしてみましょう。
<dt>お名前
<span class="form-required">必須</span>
</dt>
<dd>
<input type="text" name="name" class="form-input" value="{{ old('name') }}">
@error('name')
<div class="error"><span>{{ $message }}</span></div>
@enderror
</dd>
6行目でバリデーションルールに定義した'name'
にエラーがあるか判定しています。あれば7行目を表示し、なければ7行目をとばします。
7行目には{{ $message }}
という記載がありますが、これによりこの項目で発生しているエラー内容を表示出来るのです。
つまり、以下の様にたったこれだけのことです。
@error('name')
エラーがあるときのみ表示されるメッセージ。
{{ $message }}部分でエラー内容が表示されます。
@enderror
@error('name')
の、'name'
部分はバリデーションする対象によって変わります。
対して{{ $message }}
は常にこれでOK。
ですのでコピペして他の項目用のエラーとして貼り付けるなら、'name'
部分を変えれば動作します。
エラーを目立たせるためにしていること
以下の様に、エラーメッセージにclass="error"
のようにクラス名を付けておけば、今回のようにCSSでエラーの色を変えられます。
@error('name')
<div class="error"><span>{{ $message }}</span></div>
@enderror
今回は以下の様にCSSを設定しています。
.error span {
background-color: #f0ea94;
color: #ff0000;
font-weight: bold;
}
背景色の設定、文字色の設定、太字設定となりますね。
さらに強調させる
エラーになった箇所を、強調表示させるようなことも、実務ではよくありますね。それを実現してみたいと思います。
コード
Laravelのミドルウェアにより、自動でセットしてくれる$errors
という変数を使うことが可能です。
この変数は、Illuminate\Support\MessageBag
のインスタンスであり、エラー表示に関する様々なメソッドをサポートしています。
ここでは引数で与えたフォーム要素にエラーがあるかどうかをBoolで返す、$errors->has('name')
というメソッドを使います。
<dt>お名前
<span class="form-required">必須</span>
</dt>
<dd>
<input type="text" name="name"
class="form-input{{ $errors->has('name')? ' error' : '' }}"
value="{{ old('name') }}">
@error('name')
<div class="error"><span>{{ $message }}</span></div>
@enderror
</dd>
実際のエラー画面
スクリーンショットはこんな感じです。入力欄に赤線と背景に色をつけました。
コード解説
<input type="text" name="name"
class="form-input{{ $errors->has('name')? ' error' : '' }}"
value="{{ old('name') }}">
{{ $errors->has('name')? ' error' : '' }}
部分で三項演算子を使っています。
ここでの三項演算子部分は、$errors->has('name')
がtrue
、つまりエラーだったら、' error'
、false
だったら空文字の''
を返します。
すなわち'name'
にエラーがあれば、以下のHTMLが生成されます。
<input type="text" name="name" class="form-input error" value="">
そうでない場合は以下のHTMLが生成されます。
<input type="text" name="name" class="form-input" value="">
そのため以下のようなCSSを定義しておけば、エラー時のみ見栄えが変わるのです。
.form-input.error{
border:2px solid #ff0000;
background-color:#eee;
}
エラーは最上部に出したい
根強く昔からあるのが、エラーの情報は最上部に全て出したいというケースです。こちらも、これまでの修正から続ける形で実装してみたいと思います。
コード
フォームの始まり部分を修正します。
<form action="{{ url('/contact/inquiry') }}" method="post">
@csrf
@if ($errors->any())
<div class="error-index">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
<!-- ~省略~ -->
実際のエラー画面
以下がスクリーンショットですが、ちょっとくどいですね。これを出すなら、下の方のエラーは不要かと思います。
コード解説
@if ($errors->any())
<div class="error-index">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
1行目で、いずれかにエラーがあるか判定します。なければ9行目以降まで無視されます。
エラーがある場合、4行目~6行目までforeach
ループを回し、エラーを1つずつ表示しています。
最終系
ここでの最終系とします。上も下も詳細にエラーを出すのはちょっとくどいので、上はエラーがあった旨だけ表示させて終わりとしたいと思います。
実際のエラー画面
最後はスクリーンショットを見た方が早いです。
コード解説
先ほどいじったところがくどかったので、個別のエラーは出さずに、簡単にとどめることにしました。
<form action="{{ url('/contact/inquiry') }}" method="post">
@csrf
@if ($errors->any())
<div class="error-index">
<p>⚠️エラーが発生しました。以下の赤文字のエラー箇所をご確認ください。</p>
</div>
@endif
<dl class="form">
先ほどと比べ、プログラム的な部分はいじっていません。単にHTMLでエラーメッセージを表示させただけです。3行目~7行目の間ですね。
しいて挙げる部分があるとすれば、5行目のp
タグ開始直後は、UTF-8で使える警告の絵文字です。あくまで簡易的なものなので、実際にはSVGなどで作ってあげると良いでしょう。
まとめ
今回はステップ by ステップ形式で、フォームのエラー表示を変えていきました。この全てを使う……というわけではなく、あなたのウェブアプリケーションに適したエラーメッセージを出すのに役立てていただければと思います。
本ページのコードを利用した実例は、以下のページで解説していますので興味のある方はご覧ください。
本ページではPHP/Laravelの他、HTML/CSSなどの技術も使用しました。PHP/Laravel使いは、HTML/CSSも理解しておくと仕事の幅が広がりますよ。
最後になりますが、この例のフォームエラーのCSSデザインは説明用に簡単に作っています。実際にはサイトの表現にあった色使いなどをしてあげると、よりクールなWebアプリケーションに近づくでしょう。
デザインも……となると大変ですが、フリーランスのエンジニアになりたい方は、そのあたりも学んでおくとベターですね。
コメント