[Laravel6] 条件によってバリデーションの内容を変える方法 

## バージョン情報
- PHP 7.4.2
- Laravel 6.2

## 実現したいこと

こんな感じのラジオボタンとテキストの入力フォームがあり、
![スクリーンショット 2021-01-28 2.00.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518222/0da5cb4a-8c0f-3615-c8e3-c5f396656918.png)

```index.html
<input type="radio" name="type" value="A"><label>A</label>
<input type="radio" name="type" value="B"><label>B</label>
<br>
<input type="text" name="text">
```

- **Aが選択されている時は、textが整数であること**
- **Bが選択されている時は、textが文字列であること**
- **type, textは必ず入力されていること**

こんなバリデーションをしたい。

## 結論

```PostTextRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;

class PostTextRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'type' => 'required',
            'text' => 'required'
        ];
    }
    public function withValidator(Validator $validator)
    {
        $validator->sometimes('text', 'required | integer', function ($input) {
            return $input->type === 'A';
        });

        $validator->sometimes('text', 'required | string', function ($input) {
            return $input->type === 'B';
        });
    }
}

```

## 重要なところ

```php
public function withValidator(Validator $validator)
    {
        $validator->sometimes('text', 'required | integer', function ($input) {
            return $input->type === 'A';
        });

        $validator->sometimes('text', 'required | string', function ($input) {
            return $input->type === 'B';
        });
    }
```

## 解説

### 元のコード
元々はこんな感じの記述でした。

```TextController.php

public function post(Request $request)
{
    // バリデーションルールの配列を呼び出す
    $validation_rules = $this->rules();

    // typeがAかBかによってバリデーションを追加する
    if ($request->input('type') === 'A') {
        $validation_rules['text'] .= '|integer'; 
    } elseif ($request->input('type') === 'B') {
        $validation_rules['text'] .= '|string';
    }
    // バリデーション実行
    $request->validate($validation_rules);

    // postの処理...
}

protected function rules() 
{
    return [
        'text' => 'requied',
        'type' => 'requied'
    ];
}
```

これでも期待通りの動きはしてくれるけど、Controllerに全部書いちゃってるし、if文でバリデーションを追加するとかなんかダサい。

### withValidator()というのを使うといい感じにできるらしい。
[ドキュメント](https://laravel.com/docs/5.4/validation#conditionally-adding-rules)
[参考にした記事](https://qiita.com/hokutoasari/items/3dcfe0eaeb0200b56096)

書き方としては、

```php
public function withValidator(Validator $validator)
    {
        $validator->sometimes('バリデーションを行うフィールド', 'バリデーション | バリデーション', function ($input) {
            return バリデーションをする条件;
        });
    }
```

なので、今回のパターンに当てはめると、

```PostTextRequest.php
public function withValidator(Validator $validator)
    {
        // textが整数かどうかのバリデーションを追加したい
        $validator->sometimes('text', 'required | integer', function ($input) {
            // typeがAだった時に
            return $input->type === 'A';
        });
        // textが文字列かどうかのバリデーションを追加したい
        $validator->sometimes('text', 'required | string', function ($input) {
            // typeがBだった時に
            return $input->type === 'B';
        });
    }
```

```TextController.php
public function post(PostTextRequest $request)
{
    // postの処理...
}
```

これでControllerはスッキリするし、スマートに書ける（気がする）。

ご指摘、アドバイスお待ちしております。