【Laravel】メール送信用入力フォームのバリデーション（validation）設定方法。コントローラを使ったバリデーションとエラーメッセージの変更

Laravelのメール送信機能の一環で、入力フォームのバリデーションを設定する方法について。

>メール送信機能の作成方法は以下を参照。
・[【Laravel】Localhostでgmailを使ってメールを送信する方法。Mailableを使わない方法](https://qiita.com/yuta-38/items/5db343324b967046f7e1)

>・[【Laravel】Mailableを使ってメールを送信する方法。データや画像を添付する方法や入力データをメール本文に渡す方法](https://qiita.com/yuta-38/items/77543199f1150d71e2bf)


[Larael公式 バリデーション](https://readouble.com/laravel/7.x/ja/validation.html)


##目次

1. [バリデーションの記述場所](#バリデーションの記述場所)
2. [バリデーションのメソッド](#バリデーションのメソッド)
3. [バリデーションルール一覧](#バリデーションルール)
4. [コントローラにバリデーションを実装する方法](#コントローラにバリデーションを実装する方法)
    5. [コントローラの編集](#1-コントローラの編集)
    6. [コンタクトフォーム（ビュー）の編集](#2-コンタクトフォームビューの編集)
    7. [バリデーションの確認](#3-バリデーションの確認)
8. [エラーメッセージの変更](#エラーメッセージの変更)
    9. [validation.phpのcustom配列に追記する](#1-validationphpのcustom配列に追記する)
    10. [validation.phpの本文を書き換える](#2-validationphpの本文を書き換える)
    11. [日本語の言語ファイルを作成する](#3-日本語の言語ファイルを作成する)
12. [Varidatorファサードを使ったバリデーション](#varidatorファサードを使ったバリデーション)
12. [フォームリクエストでバリデーションする方法](#フォームリクエストでバリデーションする方法)




<br>
##バリデーションの記述場所
バリデーションの記述場所は２パターンある。
**(1) コントローラ**
**(2) フォームリクエスト**

簡単なバリデーションであればコントローラへの記述で十分。

フォームリクエスト（ファイル）を使う場合は、そのクラスをコントローラで読み込む。


<br>
**▼フォームリクエストを使うメリット**

- バリデーションの処理のみを書けるため、**コントローラがシンプルで可読性が上がる**
- **エラーメッセージを各フォームリクエスト毎に設定**できる。
- 複数のフォームリクエストを作成することでバリデーションのパターンをいくつも持てる。


<br>
###バリデーションのメソッド
バリデーションのメソッドは、Requestファサードの**validateメソッド**を使うパターンと、**validatorファサード**のメソッドを使うパターンが用意されている。

若干処理の記述方法が違ったり、エラー発生時の挙動の違いがある。


<br>
##validateメソッドとValidatorファサードの違い
validateメソッドは例外発生時に自動で元のページにリダイレクトする。

一方、Validatorファサードは自動リダイレクト機能が実装されていないので、使いたい場合は自分で記述するか、Validatorファサードのvalidationメソッドを呼び出す。


###呼び出し方法

**▼validateメソッド**

```php:
$validatedData = $request->validate([
   '属性名' => 'バリデーションルール',
   'title' => 'required|unique:posts|max:255',
   'body' => 'required',
]);
```

<br>
**▼Validatorファサード**

```php:
$validator = Validator::make($request->all(), [
            '属性名' => 'バリデーションルール',
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);
```

<br>
###Validatorファサードのリダイレクト実装方法

####▼Validatorファサードの中でvalidateメソッドを使う例

```php:
Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();
```

<br>
####▼Validatorファサードでリダイレクト処理を自分で記述する例

```php:
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
            return redirect('post/create')
                        ->withErrors($validator)
                        ->withInput();
        }
```



<br>
##バリデーションルール
バリデーションを実際に記述する際は、以下のようにバリデーションルールをパイプ（ | ）でつないでいく。

```
'対象の属性' => 'ルール1|ルール2|ルール3|,,,',
```

ルールは１から順に適用される。

バリデーションで使えるルールは多数用意されている。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/1845121c-98d1-baf3-f2ac-c176e609c152.png)|
|:--|

[バリデーションルール一覧](https://laravel.com/docs/8.x/validation#available-validation-rules)




<br>
###主なバリデーションルール

| ルール名 | 内容 |
|:-:|:--|
| required  | 値が必須。ない場合はエラーになる。  |
| email  | e-mailのフォーマットのみ許容する  |
| image  | イメージ画像 (jpg, jpeg, png, bmp, gif, svg, or webp)のみ許容する  |
| max:value  | 指定した数字以下のみ許容。  |
| min:value  | 指定した数字以上のみ許容。  |
| url  | urlのみ許容する。  |
| bail  | 例外が発生した時点でバリデーションチェックを終了する  |
| accepted  | アクティブかどうかを調べる。'yes', 'on', 1, trueのみ許容する。  |
|  after:date | 指定日以降のみ許容する  |
| alpha_num  | アルファベットと数字のみ許容する  |


[@fagaiさんのページ](https://qiita.com/fagai/items/9904409d3703ef6f79a2)がわかりやすいです。


<br>
##コントローラにバリデーションを実装する方法
編集するのは２つのファイルのみでOK。（既にメール送信ができる状態）

###1. コントローラの編集
バリデーションの設定はとても簡単。以下コードをsendアクションに追加するのみ。

```php:追記する内容
 $validateData = $request->validate([
            'name' => 'required|string|max:10|min:3',
        ]);

        $data = $validateData;
```

・`$request->validate([バリデーションの条件])`
validateメソッドを使用。

・`'name' => 'required|string|max:10|min:3'`
属性名nameに対して、required(必須)、string(文字列)、max:10（10文字以内）、min:3（３文字以上）の条件を割り当て。

・`$data = $validateData;`
バリデーション後のデータを変数dateに入れる。
例外があった場合はそのエラーメッセージが入る。


<br>
**▼コントローラの記述例**

```php:ValidateController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Mail;                   //追記
use App\Mail\ValidatedMail; //追記

class ValidateController extends Controller
{
    public function index() //コンタクトフォームの表示
    {
        return view('contact.validate');
    }

    public function send(Request $request)  //メールの自動送信設定
    {
        //バリデーション
        $validateData = $request->validate([
            'name' => 'required|string|max:10|min:3',
        ]);

        $data = $validateData;

        //メール送信処理
        Mail::to('xxx@gmail.com')
                ->send(new ValidatedMail($data));

        return back()->withInput()
                     ->with('sent', '送信完了しました。');    //送信完了を表示
    }
}
```


<br>
###2. コンタクトフォーム（ビュー）の編集
例外が発生したときに、例外の内容をビューに表示できるようにする。

```php:追記内容
@error('name')
  <p style="color:red;">{{ $message }}</p>
@enderror
```

これを追加するだけで、エラー発生時に内容が表示される。

バリデーションで**例外が発生すると元のページにリダイレクト**され、その際に、**エラー内容がそのページに渡される**。

追記したコードは**受け取ったエラー内容を表示する処理**となる。

**・`@error('属性名')`**
指定した属性でエラーが発生した場合に以下処理が表示される。
エラー内容は自動的に`$message`に入る。

`@enderror`で処理を閉じる。


<br>
**・`<p style="color:red;">{{ $message }}</p>`**
pタグ赤色で表示するように指定。ここは別になんでもいい。
大切なのは、`$message`にエラーメッセージが格納されているということ。


<br>
###3. バリデーションの確認
実際にブラウザでバリデーションが機能しているか確認してみる。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/64ce5e04-bb23-be07-888a-cba417231214.png)|
|:--|

 ↓文字数が２文字以下

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/6bee97d2-a439-dc8e-fb9b-ee5a88cb1c4c.png)|
|:--|

3文字以上じゃなきゃダメというエラーメッセージが表示される。


<br>
▼その他のエラーもちゃんと表示される。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/7bb3c19c-cec7-fc06-5e52-6c154a4faba3.png)|
|:--|

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/63de33d6-872a-f683-22ed-6bb8253097c2.png)|
|:--|



<br>
##エラーメッセージの変更
デフォルトの状態では、エラーメッセージは決められたテキスト（英語）が表示される。

####デフォルトのエラーメッセージの置き場所
resources > lang > en > validation.php

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/5f0b1268-f1f7-6ef1-edf7-14749a0e10e8.png)

**▼minの場合**

```php
    'min' => [
        'numeric' => 'The :attribute must be at least :min.',
        'file' => 'The :attribute must be at least :min kilobytes.',
        'string' => 'The :attribute must be at least :min characters.',
        'array' => 'The :attribute must have at least :min items.',
    ],
```

入力された型によってメッセージが変わるようになっている。

- `:attribute`に指定した属性名が入る。
- `:min`に指定した文字数が入る。


<br>
###エラーメッセージの変更
コントローラにバリデーションを直接記述する場合のエラーメッセージ変更方法は３つある。

1. validation.phpのcustom配列に追記する
2. validation.phpの本文を書き換える
3. 日本語の言語ファイルを作成する

>Voridatorファサードやフォームリクエストを使う場合は、ファイルに直接記述できる。



<br>
##1. validation.phpのcustom配列に追記する
最もシンプルな方法。No2と異なり変更箇所がわかりやすい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/5f0b1268-f1f7-6ef1-edf7-14749a0e10e8.png)
このファイルの下の方にある、`custom`部分に追記する。

```php:validation.php
    'custom' => [
        'attribute-name' => [
            'rule-name' => 'custom-message',
        ],
        //以下追記
        'name' => [
            'min' => ':min 文字以上で入力してください'
        ],
    ],
```

　↓ 保存してバリデーションを実行

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/13365f30-9765-b7b0-b7dc-80e73e0b61e8.png)|
|:--|

日本語化に成功。



<br>
###2. validation.phpの本文を書き換える
例えば、`min`の`string`を書き換える場合は以下のようになる。

```php:validation.php
    'min' => [
        'numeric' => 'The :attribute must be at least :min.',
        'file' => 'The :attribute must be at least :min kilobytes.',
        // 'string' => 'The :attribute must be at least :min characters.',
        'string' => '名前は :min 文字以上で入力してください.',
        'array' => 'The :attribute must have at least :min items.',
```

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/dbcae78c-24df-fb1e-5196-2c7b604b9a96.png)|
|:--|


<br>
##3. 日本語の言語ファイルを作成する
日本語の言語ファイルを作成し、設定言語を日本語に切り替える方法。

本格的に日本語化したい場合は使えるが、翻訳作業に時間がかかる、、


####3-1. jaディレクトリを作成
enディレクトリ配下をコピーしてjaディレクトリに貼り付け。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/900d033e-4a33-9fb2-969f-75c12629598c.png)


###3-2. validation.phpのメッセージを書き換える
jaディレクトリのファイルを日本語化する。
大変なので、今回は`required`のみ日本語化

```php:validation.php
'required' => 'この項目は必須です。',
```


####3-3. 設定言語をjaに変更する
config > app.php　のlocale（言語設定）をenからjaに変更する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/71fe5a4d-228a-ab52-ea4c-bd4760ed0fc2.png)

```php:app.php
    /*
    |--------------------------------------------------------------------------
    | Application Locale Configuration
    |--------------------------------------------------------------------------
    |
    | The application locale determines the default locale that will be used
    | by the translation service provider. You are free to set this value
    | to any of the locales which will be supported by the application.
    |
    */

    'locale' => 'ja',
```


以上で設定完了。

<br>
**▼検証結果**

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/c7d56183-1efb-67b9-a6f0-fce652b7974a.png)|
|:--|

jaディレクトリの内容が適用できた。


<br>
###日本語翻訳版validation.php
Laravel公式ページに[翻訳後のvalidation.php](https://readouble.com/laravel/8.x/ja/validation-php.html
)あります。



<br>
##Varidatorファサードを使ったバリデーション
requestファサードのvalidateメソッドではなく、Varidatorファサードを使った場合の記述方法について。

Validatorファサードを使う場合はコントローラの冒頭に以下を記述する。

```php:追記内容
use Illuminate\Support\Facades\Validator;
```

<br>
Validatorのmakeメソッドでバリデーションを定義する。**makeメソッドは引数を3つ**とる。

```php:
Validator::make(対象データ, バリデーションルール, エラーメッセージ)
```

- 第１引数：バリデーション対象のデータ
- 第２引数：バリデーションルール
- 第３引数：カスタムエラーメッセージ（なくてもいい）

バリデーションルールやエラーメッセージは変数で渡すことが多い。

ルールには`$rules`, エラーメッセージは`$messages`を渡すなど。


<br>
##実例
###1. コントローラの編集
コントローラのsendアクションに以下を追加する。

```php:追記内容
use Illuminate\Support\Facades\Validator;
```

Validatorファサードを使うために冒頭に表示する。
<br>

```php:追記内容
        //バリデーションルール
        $rules = [
            'name' => 'required|min:3|max:10',
        ];

        //Validator
        $validator = Validator::make($request->all(), $rules)
                    ->validate();       
```

**・`$rules`**
属性に対しバリデーションルールを設定する。
カンマでつないで複数設定できる。


**・`$request->all()`**
渡されたすべてのデータをバリデーション対象とする。


**・`->validate();`**
validateメソッドで自ページに自動リダイレクトする。

この処理は以下記述と同じ。

```php:
        if ($validator->fails()) {
            return redirect('validate')
                        ->withErrors($validator)
                        ->withInput();
        }
```

バリデーションで例外が発生したら、URI：validateにリダイレクト（ここでは自ページ）

・`withErrors()`
リダイレクト画面に`$errors`でエラーデータを渡す。

・`withInput()`
フォームの入力内容をリダイレクト画面に渡す。`old()`で呼び出せる。


<br>
##コントローラの記述例
コントローラの記述は以下のようになる。

```php:ValidateController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Mail;                   //追記
use App\Mail\ValidatedMail; //追記
use Illuminate\Support\Facades\Validator; //追記

class ValidateController extends Controller
{
    public function index() //コンタクトフォームの表示
    {
        return view('contact.validate');
    }

    public function send(Request $request)  //メールの自動送信設定
    {
        //バリデーションルール
        $rules = [
            'name' => 'required|min:3|max:10',
        ];

        //Validator
        $validator = Validator::make($request->all(), $rules, $messages)
                    ->validate();

        Mail::to('xxx@gmail.com')
                ->send(new ValidatedMail($validator));

        return back()->withInput()
                     ->with('sent', '送信完了しました。');    //送信完了を表示
    }
}
```


<br>
###2. コンタクトフォーム（ビュー）の編集
例外が発生したときに、例外の内容をビューに表示できるようにする。

```php:追記内容
@error('name')
  <p style="color:red;">{{ $message }}</p>
@enderror
```

これを追加するだけで、エラー発生時に内容が表示される。

バリデーションで**例外が発生すると元のページにリダイレクト**され、その際に、**エラー内容がそのページに渡される**。

追記したコードは**受け取ったエラー内容を表示する処理**となる。

**・`@error('属性名')`**
指定した属性でエラーが発生した場合に以下処理が表示される。
エラー内容は自動的に`$message`に入る。

`@enderror`で処理を閉じる。


<br>
**・`<p style="color:red;">{{ $message }}</p>`**
pタグ赤色で表示するように指定。ここは別になんでもいい。
大切なのは、`$message`にエラーメッセージが格納されているということ。


<br>
###3. バリデーションの確認
実際にブラウザでバリデーションが機能しているか確認してみる。



**▼実行結果**

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/c90cca2d-82c7-6298-8cae-21872c05253d.png)|
|:--|

バリデーション成功。


<br>
##エラーメッセージをカスタムする
エラーメッセージをカスタムする方法は４つある。

**1. validation.phpのcustom配列に追記する**
**2. validation.phpの本文を書き換える**
**3. 日本語の言語ファイルを作成する**
**4. 第３引数でメッセージを渡す**


No.1~3はRequestファサードのvalidateメソッドを使った場合も共通。[validateメソッドのカスタムメッセージ表示方法](https://qiita.com/yuta-38/items/bc1dd1e63749186a4a7b#%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E5%A4%89%E6%9B%B4)

**No.4がValidatorファサード特有の便利機能。**


<br>
##第３引数でメッセージを渡す方法
ルールの指定方法は２つある。

**（１）ルール毎にメッセージを指定する場合**
・`'ルール' => 'カスタムメッセージ'`


**（２）属性に適用したルール毎にメッセージを指定する場合**
・`'属性名.ルール' => 'カスタムメッセージ'`

この記述であれば、formの中に同じルールが複数ある場合に、メッセージの出しわけができる。

<br>

```php:追記内容
        //バリデーションルール
        $rules = [
            'name' => 'required|min:3|max:10',
        ];

        //追記
        $messages = [
            'name.max' => ':max 文字以下で入力して下さい。',
            'name.min' => ':min 文字以上で入力して下さい。',
        ];

        //Validator
        $validator = Validator::make($request->all(), $rules, $messages)        //追記
                    ->validate();       
```

**▼実行結果**

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/663c518b-f09d-4398-d84e-2e4be70e8142.png)|
|:--|


<br>
##まとめ
Requestファサードのvalidateメソッドを使うよりも、Validatorファサードを使った方が記述がわかりやすい。（個人的見解）


<br>
<br>
##フォームリクエストでバリデーションする方法

長くなったので別記事に記述します。