【laravel】バリデーションエラーの表示と編集

# 概要
laravelではいくつかの方法でバリデーションをかけることができます。
そのため一度に投稿するとボリュームが多くなるので複数回に分けます。

[・validateメソッドによるバリデーション]()
[・FormRequestによるバリデーション]()
[・Validatorによるバリデーション]()
[・ruleオブジェクトによる検証ルールの追加]()


# エラーメッセージの表示
バリデーションエラー時に返されるメッセージの表示はビューでの処理のみで対応できます。
このエラーメッセージは`Illuminate\Support\MessageBag`のインスタンスであるerrors変数へフラッシュデータとして保存されます。
errors変数は`Illuminate\View\Middleware\ShareErrorsFromSession`によりビューへ結合されているため、バリデーションの記述方法に関係なく、いつでも共通してビューの中で$errors変数が使えます。

また、フラッシュデータは現在と直後のHTTPリクエストの間だけセッションにデータを保存して、それ以降は削除するというセッションのflashメソッドの保存方法です。


# 全てのエラーメッセージをまとめて表示する
errors変数は連想配列として保存されているため`$errors->all()`を＠foreachで取得すればまとめて表示することができます。

```php:views
@foreach ($errors->all() as $error)
  <li>{{$error}}</li>
@endforeach

// 記述方法：$errors->all()
```


# 特定のエラーメッセージを表示
エラーメッセージはまとめて表示するより、フィールドごとにエラーメッセージを表示した方が見やすいですよね。
そういう時は`$errors->first('項目名')`で指定した項目の最初の値を取得します。
この時の注意点は`if ($errors->has('項目名'))`でエラーメッセージの有無を確認してから記述することです。
`$errors->has('項目名')`はエラーメッセージの有無チェックするbool型のメソッドで、エラーメッセージがあればtrueを返します。

```php:views
@if ($errors->has('name'))
  <li>{{$errors->first('name')}}</li>
@endif

// 記述方法：$errors->first('項目名')
// ただし、$errors->has('項目名')により値の有無を確認する
```


# 複数のエラーメッセージを表示する
先程のfirestメソッドは最初の値を取得するため複数のエラーメッセージを表示することができません。
エラーメッセージが複数発生する可能性があるフォームは`$errors->get('項目名')`
でエラーメッセージを取得します。
ただし、getメソッドの値は配列で取得されるためforeachでテキストとして取得する必要があります。

```php:views
@if ($errors->has('age'))
<tr>
  <th>ERROR</th>
  @foreach($errors->get('age') as $message)
  <td> {{ $message }} </td>
  @endforeach
</tr>
@endif

// 記述方法：$errors->get('項目名')
// ただし、$errors->has('項目名')により値の有無を確認する
```


# ＠errorで特定のエラーメッセージを表示
`$errors->has('項目名')`でエラーメッセージの有無を確認せずとも、`@error('項目名')`と記述することによりエラーメッセージの有無を確認して`$message`へ値を渡すことができます。
この方法はhasメソッドとfirstメソッドと同じ要領で使用できます。
ifディレクティブによる記述を省略できるため可読性は上がりますがgetメソッドのように複数の値を取得できないことに注意です。

```php:views
@error('name')
  <li>{{$message}}</li>
@enderror

// 記述方法：@error（'項目名'）、$massage
```


# エラーメッセージの日本語化
日本向けのサービスでエラーメッセージが英語だと不親切なので日本語にします。

## 日本語言語の準備

まず、日本語の言語フォルダを用意します。
ここでは`resources/lang`にある`en`フォルダをコピペして`ja`と名前を変えるだけで大丈夫です。
langディレクトリにはバリデーション以外にもログインなどで表示するメッセージが保存されています。

また、GitHubに日本語言語のファイルセットがあるのでjaディレクトリだけ作成して、中身のファイルはクローンして作成すると楽に日本語化の準備ができます。
この方法の場合は次の段落は飛ばして大丈夫です。
[Laravel 日本語言語ファイルセット ](https://github.com/rito328/Laravel-Japanese-Language-fileset)

```:ディレクトリ
resources
├─ lang
|  ├─ ja
```

## バリデーションメッセージを日本語へ
コピペしてフォルダ名を変えたja内に`validation.php`があります。
この中身を以下のリンクの内容へコピペします。
[validation.php言語ファイル](https://readouble.com/laravel/6.x/ja/validation-php.html)
これで日本語化の準備は完了です。

`validation.php`に記述されている内容がバリデーションメッセージとして表示されるため、オリジナルのエラーメッセージを追加することもできます。
エラーメッセージの追加は[ruleオブジェクトによる検証ルールの追加 / resourcesのlangに登録](https://qiita.com/gone0021/private/7374293c270a99bbf6d8#resources%E3%81%AElang%E3%81%AB%E7%99%BB%E9%8C%B2)で簡単に紹介しています。

## ロケールの設定
`config/app.php`のlocale設定を変更します。
ここでは使用する言語ディレクトリを指定しています。
ロケールには`locale`と`fallback_locale`がありますが`locale`の設定のみを変更します。
`fallback_locale`は`locale`でメッセージの用意がない場合などで使用されるのでデフォルトのままにしておくのが無難と思います。
以上で日本語化の完了です。


```:ディレクトリ
config
├─ app.php
```

```php:validation
// 中略
'locale' => 'en', // ここを'ja'へ
```

```php:validation
// 中略
'locale' => 'ja',
```

`locale`と`fallback_locale`ともに言語設定のないものに変更したら`validation.required`のようなエラーメッセージとなりました。
一応何かしらの表示は処理されるようですが、バリデーションの検証ルールが表示されるのはよくないですね。

# 共通のバリデーションメッセージを編集する
`resources/lang`で設定した言語のディレクトリ内の`validation.php`を編集します。
直接ルールごとにエラーメッセージを編集することもできますが、ここでは`costom`配列内で編集していきます。
costom配列に記述することにより、`検証する値`を連想配列のキーとして、その値に対応するルールごとにエラーメッセージを作成できます。

```php:検証ルールの例
$validate_rule = [
  'name' => 'required',
  'age' => 'integer | between:0,150',
  'sex' => ['max:1', 'regex:/^[男|女]+$/u'],
];
```

```php:validation.php（メッセージ）
// ...中略...
'custom' => [
  'age' => [
    'numeric' => '整数で入力してください',
    'between' => '0～150で入力してください' 
  ],
  'sex' => [
    'regex' => '男か女で入力してくださいい' 
  ],

],
// 中略...
```

```:表示例
name（required）：The name field is required.
age（integer）：整数で入力してください
age（between）：0～150で入力してください
sex（max:1）：The sex may not be greater than 1 characters.
sex（regex:/^[男|女]+$/u）：男か女で入力してください
```


## 検証ルールごとにメッセージを編集

```php:validation.php
// ...中略...
'custom' => [
  'attribute-name' => [
    'rule-name' => 'custom-message',
  ],
],
// 中略...
```


# 参考
[Laravel 6.x バリデーション / バリデーションエラー表示](https://readouble.com/laravel/6.x/ja/validation.html#quick-displaying-the-validation-errors)
[Laravel 6.x バリデーション / 言語ファイルでカスタムメッセージ指定]
(https://readouble.com/laravel/6.x/ja/validation.html#localization)
[Laravel 6.x validation.php言語ファイル]
(https://readouble.com/laravel/6.x/ja/validation-php.html)
[入門者のためのLaravelのValidationとエラーメッセージ / エラーメッセージの日本語化]
(https://reffect.co.jp/laravel/laravel_validation_understanding#i-10)
[エラーメッセージの日本語化]
(https://www.ritolab.com/entry/40#aj_5)
[Laravel 日本語言語ファイルセット ]
(https://github.com/rito328/Laravel-Japanese-Language-fileset)