【laravel】Validatorによるバリデーション

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

[・validateメソッドによるバリデーション]()
[・FormRequestによるバリデーション]()
[・ruleオブジェクトによる検証ルールの追加]()
[・バリデーションエラーの表示と日本語化]()

# Validatorとは
Validatorはlaravelのファサード（標準クラス）として提供されている機能です。
バリデーションは実行するが、エラー時はフォームにリダイレクトせず別の処理を実行したい場合や、postの値以外でバリデーションを実行したい場合に適した記述方法がValidatorファザードです。

# コントローラーとルーティングの作成
例としてFormControllerでコードを記述するため、、コントローラーとルーティングを作成します。

## ルートの定義
PostControllerクラスのvalidatesメソッドへのルーティングを記述します。

```php:web
Route::post('sample', 'FormController@postValidates');
```

## コントローラーの作成
まずはバリデーションを実行するFormControllerクラスを作成します。
Controllerの作成なので段落だけ付けて詳細は割愛します。

### コマンド
```:コマンド
php artisan make:controller FormController
```

### ディレクトリ構造

```:ディレクトリ
app
├─ Http
|  ├─ Controllers
|  |  ├─ FormController.php
```

### 作成されるファイル
```php:FormController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FormController extends Controller
{
    //
}
```

# バリデーションの作成
Validatorファザードを使用するのでValidatorをuseします。

次に作成したPostControllerにpostValidatesというメソッドを作成してバリデーションの処理を記述していきます。
（ここのメソッド名はなんでもいいです。）

```php:FormController
use Illuminate\Support\Facades\Validator;
// または
use Validator; // Validatorだけでも実行できる

public function postValidates(Request $request)
{
  //
}
```


## バリデーションの記述
Validatorファザードでバリデーションを実行するにはmakeメソッドを使用してインスタンスを作成します。
引数は`Validator::make('値の配列', '検証ルールの配列')`で記述します。

また、バリデーションの正否はValidatorクラスのfailsメソッドで判定します。
failsメソッドは、バリデーションの失敗をtrueで返して成功をfalseで返すbool型のメソッドです。

```php:FormController
public function postValidates(Request $request)
{
  $validator = Validator::make($request->all(), [
    'name' => 'required',
    'age' => 'integer | between:0,150',
    'sex' => ['max:1', 'regex:/^[男|女]+$/u'],
  ];)

// 記述方法：Validator::make('値の配列', '検証ルールの配列');

  if ($validator->fails()) {
    return redirect('/errorpage')
    ->withErrors($validator)
    ->withInput();
  } else {
    return view('sample.index', ['msg' => 'OK']);
  }

// 記述方法：if($validator->fails()) {失敗時の処理} else {成功時の処理}
}
```

### Validator::make
makeメソッドは`['値の配列'=>'検証ルールの配列']`となっています。
ここでは値の配列を`Validator::make($request->all()`として入力された全ての値を取得しています。


検証ルールの配列は連想配列で`['postしてきた値'=>'検証ルール']`
検証ルールを複数設けたい場合は検証ルールの間に`|`を入れて区切ります。
もしくは、配列のバリュー（検証ルール）を配列にして`,`で区切って記述することもできます。

```php:Validator::make
$request->validate([
  'name' => 'required',
  'age' => 'integer | between:0,150',
  'sex' => ['max:1', 'regex:/^[男|女]+$/u'],
];)

// 記述方法：['検証の値'=>'検証ルール1 | 検証ルール2',]
// もしくは、['検証の値'=>['検証ルール1', '検証ルール2'],]
```

```:使用した検証ルール
required：何かしらの値があること
integer：半角整数であること
between:a,b：aからbまでの数字
max:a：文字数の最大値がa個
regex:：PHPのpreg_match関数
```

### $validator->fails
ここでは`if`でバリデーションの失敗を判定、を保存、`withInput`でold()へ入力された値を保存、`withErrors`で$errorsへエラーメッセージを保存、`redirect`でerrorpageにリダイレクト、という一連の動作を記述しています。

redirectは指定のアドレスへ移動するメソッドでPHPのheaader()メソッドのようなものです。
withErrorsは引数の値を$errors変数へ保存してリダイレクト先まで引き継ぐメソッドで、withInputは送信されたフォームの値をInput::old()へ引き継ぐメソッドです。

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

// 記述方法：
// バリデーションが失敗したなら
// Validatorインスタンスの値を$errorsへ保存
// 送信されたフォームの値をInput::old()へ引き継ぐ
```


## validateメソッドによるへリダイレクト
validateメソッドは、POSTされた値のバリデーションに成功するとコードは通常通り続けて実行され、バリデーションに失敗すると自動的に例外が投げられユーザーへ適切なエラーメッセージが返されるメソッドです。


参考：[validateメソッドによるバリデーション](https://qiita.com/gone0021/private/5699c29c7ce64f08b8d2#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E6%BA%96%E5%82%99)

```php:FormController
public function postValidates(Request $request)
{
  Validator::make($request->all(), [
    'name' => 'required',
    'age' => 'integer | between:0,150',
    'sex' => ['max:1', 'regex:/^[男|女]+$/u'],
  ])->validate(); // validateメソッドによるリダイレクト
  return view('sample.index', ['msg' => 'OK']);
}
```


## エラーメッセージのカスタマイズ
先程は`Validator::make('値の配列', '検証ルールの配列')`で記述しましたが、Validator::makeメソッドでは`Validator::make('値の配列', '検証ルールの配列', 'エラーメッセージ')`として記述することもできます。
ただし、エラーメッセージは検証ルールごとに設定する必要があるため、エラーメッセージの設定がない検証ルールはデフォルトのエラーメッセージが返されます。

ここでは検証のルールとエラーメッセージを変数として記述してmakeメソッドの引数に当てます。

```php:
public function post(Request $request) {
  $rulus = [
    'name' => 'required',
    'age' => 'integer | between:0,150',
    'sex' => ['max:1', 'regex:/^[男|女]+$/u'],
  ];

  $message = [
    'name.required' => '名前を入力してください',
    'age.numeric' => '整数で入力してください',
    'age.between' => '0～150で入力してください'
    'sex.regex' => '男か女で入力してください',
  ];

  $validator = Validator::make($request->all(), $rulus, $message);

  if ($validator->fails()) {
    return redirect('/hello')
    ->withErrors($validator)
    ->withInput();
  }
  return view('hello.index',['msg'=>'正しく入力されました!']);
}

```

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


## クエリーにバリデータを適用
Validatorファサードではpost以外にもgetで取得した値にバリデーションを実行することができます。
記述方法はpostValodatesで作成した内容とほぼ同じなので解説は割愛します。
大きな違いはルーティングの処理をpostではなくgetで記述していることくらいです。


### ルートの定義
PostControllerクラスのpostValidatesメソッドへのルーティングを記述しま。

```php:web
Route::get('sample', 'FormController@getValidates');
```

### バリデーションの作成
ここではエラーメッセージを返すという処理ではなく、処理に成功したか失敗したかのみを表示させる記述をします。

```php:FormController
public function index(Request $request)
{
  $validator = Validator::make($request->query(), [
    'id' => 'required',
    'name' => 'required',
  ]);

  if ($validator->fails()) {
    $msg = 'クエリーに問題があります';
    return view('sample.form', ['msg' => $msg]);
  } else {
    $msg = 'ようこそ○○さん';
    return view('sample.index', ['msg' => $msg]);
  }
}
```



# 参考
[Laravel 6.x バリデーション / バリデータの生成]
(https://readouble.com/laravel/6.x/ja/validation.html#manually-creating-validators)
[Laravel 6.x ファサード]
(https://readouble.com/laravel/6.x/ja/facades.html)
[Laravelのvalidationメソッドでバリデーションを実装する入門編 / 自動リダイレクトは行わないバリデーション]
(https://www.ritolab.com/entry/40#aj_3_1)
[【Laravel】ファサードの仕組み – 実装を読んで理解する]
(https://public-constructor.com/laravel-what-is-facade/)
[【保存版】バリデーションルールまとめ]
(https://www.wakuwakubank.com/posts/376-laravel-validation/)