Spatie laravel-data ライブラリ バリデーションの設定

# 概要

- laravel-dataにてバリデーションを設定する方法をまとめる。

# 前提

- 今回の説明には下記の説明で取り扱ったコードを使用する。
    - [Spatie laravel-data ライブラリ リクエストを定義する](https://qiita.com/miriwo/items/3afb6651b83f2ec2b9f1)

# 方法

- バリデーション設定方法は下記の三種類存在する。
    1. ライブラリが用意しているルール（属性）をアノテーションで設定
    1. Rule属性をアノテーションで記載して通常のformRequestと同じ記法で設定
    1. rules()関数でformRequestのように設定

### ライブラリ用意の属性を使用

1. 下記のようにリクエストクラスのコンストラクター引数にアノテーションでバリデーション属性を付与する。（$nameの値を20最大20文字、$ageの値を最小1文字とするバリデーションを例に記載する。）

    ```app/Http/Requests/PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Max;
    use Spatie\LaravelData\Attributes\Validation\Min;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            #[Max(20)]
            public string $name,
            #[Min(1)]
            public int $age
        )
        {
            
        }
    }
    ```

1. ライブラリが用意してくれているバリデーション属性は下記ドキュメントにまとまっている。
    - [https://spatie.be/docs/laravel-data/v1/advanced-usage/validation-attributes](https://spatie.be/docs/laravel-data/v1/advanced-usage/validation-attributes)

### Rule属性を使用

1. 下記のようにリクエストクラスのコンストラクター引数にアノテーションでRule属性を付与する。
1. カスタムバリデーションルールを使う事ができる。
1. Rule属性の引数にformRequestと同じ方法でバリデーションルールを指定する。

    ```app/Http/Requests/PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            #[Rule(['required', max:20'])]
            public string $name,
            #[Rule(['required', 'min:1'])]
            public int $age
        )
        {
            
        }
    }
    ```

1. ちなみにバリデーションルールは上記の配列での指定と下記2つの文字列での指定、引数での指定、それぞれに対応している。
1. 文字列での指定

    ```app/Http/Requests/PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            #[Rule('required | max:20')]
            public string $name,
            #[Rule('required | min:1')]
            public int $age
        )
        {
            
        }
    }
    ```

1. 引数での指定

    ```app/Http/Requests/PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            #[Rule('required', 'max:20']
            public string $name,
            #[Rule('required', 'min:1')]
            public int $age
        )
        {
            
        }
    }
    ```

### rules()関数を使用

1. 下記のようにリクエストクラスにrules()関数を定義することでバリデーションルールを定義することもできる。

    ```app/Http/Requests/PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            public string $name,
            public int $age
        )
        {
        }
    
        public static function rules(): array
        {
            return [
                'name' => ['required', 'max:20'],
                'age' => ['required', 'min:1'],
            ];
        }
    }
    ```

1. カスタムバリデーションルールを使う事ができる。
1. 「Rule属性を使用」と同様にformRequestと同じ方法でバリデーションルールを指定する。
1. 「Rule属性を使用」と「rules()関数を使用」は併用できるようだ。
1. `Illuminate\Validation\Rule::in`などのRuleクラスを用いてバリデーションをしたい場合はこの方法で記載すると良い。下記のバリデーションはageキーに紐づく値が18、19、20のいずれかであるかをバリデーションしている。

    ```app/Http/Requests/PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Illuminate\Validation\Rule;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            public string $name,
            public int $age
        )
        {
        }
    
        public static function rules(): array
        {
            return [
                'name' => ['required', 'max:20'],
                'age' => ['required', Rule::in([18, 19, 20])],
            ];
        }
    }
    ```

# 参考文献

- [https://spatie.be/docs/laravel-data/v1/as-a-data-transfer-object/request-to-data-object](https://spatie.be/docs/laravel-data/v1/as-a-data-transfer-object/request-to-data-object)
- [https://spatie.be/docs/laravel-data/v1/advanced-usage/validation-attributes](https://spatie.be/docs/laravel-data/v1/advanced-usage/validation-attributes)