Spatie laravel-data ライブラリ データ構造の表現方法あれこれ

# 概要

- larave-dataにていろいろなデータ構造を表現するときの記載方法をまとめる。

# 並列なキー

- 下記のような構造を表現したいとする。

    ```json
    {
      "name": "Foo Bar",
      "age": 26,
      "isAdmin": true,
      "favorite": [
        "hoge",
        "fuga"
      ]
    }
    ```

- 下記のように定義する。

    ```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 bool $isAdmin,
            public array $favorite,
        )
        {
        }
    }
    ```

- バリデーションルールを付与する場合は下記のようになる。

    ```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', 'string'])]
            public string $name,
            #[Rule(['required', 'integer'])]
            public int $age,
            #[Rule(['required', 'boolean'])]
            public bool $isAdmin,
            #[Rule(['required', 'array'])]
            public array $favorite,
        )
        {
        }
    }
    ```

# ネストされたオブジェクト

- 下記の様な構造を表現したいとする。

    ```json
    {
      "user": {
        "name": "Foo Bar",
        "age": 26
      }
    }
    ```

- まずDataクラスを継承したUserクラスを定義して最も階層の深いキーと値を下記のように定義する。

    ```User.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    
    class User extends Data
    {
        public function __construct(
            #[Rule(['required', 'string'])]
            public string $name,
            #[Rule(['required', 'integer'])]
            public int $age,
        )
        {
        }
    }
    ```

- Userクラスを呼び出す。

    ```PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    use App\Http\Requests\User;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            #[Rule(['required', 'object'])]
            public User $user,
        )
        {
        }
    }
    ```

# 配列の中のオブジェクト

- 下記の様な構造を表現したいとする。

    ```json
    {
      "name": "Foo Bar",
      "age": 26,
      "family": [
        {
          "name":"Foo Bar2",
          "age": 25
        }
      ]
    }
    ```

- まずDataクラスを継承したFamilyクラスを定義して配列の中のオブジェクトを下記のように定義する。

    ```User.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    
    class Family extends Data
    {
        public function __construct(
            #[Rule(['required', 'string'])]
            public string $name,
            #[Rule(['required', 'integer'])]
            public int $age,
        )
        {
        }
    }
    ```

- FamilyクラスをDataCollectionを使って呼び出す。

    ```PostUserRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Spatie\LaravelData\Data;
    use Spatie\LaravelData\Attributes\Validation\Rule;
    use App\Http\Requests\Family;
    use Spatie\LaravelData\DataCollection;
    
    class PostUserRequest extends Data
    {
        public function __construct(
            #[Rule(['required', 'string'])]
            public string $name,
            #[Rule(['required', 'integer'])]
            public int $age,
            /** @var DataCollection<Family> */
            public DataCollection $family,
        )
        {
        }
    }
    ```

- Familyクラスの呼び出し方は複数ある。他の方法は下記参照
    - [https://spatie.be/docs/laravel-data/v1/as-a-data-transfer-object/collections](https://spatie.be/docs/laravel-data/v1/as-a-data-transfer-object/collections)