如何使用 spatie/laravel-data 嵌套相同的数据类型?

How to nest same Data type with spatie/laravel-data?

提问人:s3c 提问时间:11/11/2022 最后编辑:s3c 更新时间:11/11/2022 访问量:905

问:

我从 API 获取 JSON,我需要将其转换为递归嵌套对象。

我的对象的一个属性是一个数组,其中包含与父对象类型相同的元素。

这是我的 Data 类:

class Group extends Data
{
    /** @var \App\Data\Group[] **/
    public array $subGroups;

    public function __construct(
        public string $id,
        array $subGroups,
    ) {
        /** @var \App\Data\Group[] */
        $this->subGroups = collect($subGroups)
            ->map(fn (array $group) => Group::from($group))
            ->all();
    }
}

这是我的 JSON 响应:

[
    {
        "id": "1",
        "subGroups": [
            {
                "id": "1-1",
                "subGroups": []
            },
            {
                "id": "1-2",
                "subGroups": [
                    {
                        "id": "1-2-1",
                        "subGroups": []
                    }
                ]
            }
        ]
    },
    {
        "id": "2",
        "subGroups": []
    }
]

具有以下方法:

/**
 * @param array[] $groups
 * @return Group[]
 */
public function toGroups(array $groups): array
{
    return collect($groups)
        ->map(fn (array $group) => Group::from($group))
        ->all();
}

/**
 * @return Group[]
 */
public function toGroupsFromResponse(ResponseInterface $response): array
{
    return $this->toGroups(
        json_decode($response->getBody()->getContents(), true)
    );
}

我想返回并使用嵌套的 Group 类型对象进行对象处理,如下所示toGroupsFromResponse

# Pseudo-code
[
    Group {
        string id = '1'
        Group[] subGroups = [
            Group {
                string id = '1-1'
                Group[] subGroups = []
            },
            Group {
                string id = '1-2'
                Group[] subGroups = [
                    Group {
                        string id = '1-2-1'
                        Group[] subGroups = []
                    },
                ]
            }
        ]
    },
    Group {
        string id = '2'
        Group[] subGroups = []
    }
]

相反,所有子组都是数组的数组。

# Pseudo-code
[
    Group {
        string id = '1'
        array subGroups = [
            array {
                string id = '1-1'
                array subGroups = []
            },
            array {
                string id = '1-2'
                array subGroups = [
                    array [
                        string id = '1-2-1',
                        array subGroups = []
                    ],
                ]
            }
        ]
    },
    Group {
        string id = '2'
        array subGroups = []
    }
]

当我使用 Spatie 的旧 DataTransferObject 对象时,它有效,但我在使用新的 Data 对象时遇到了问题。

我知道这是一个宽泛的问题,但我哪里做错了?

PHP 数组 Laravel 嵌套 DTO

评论


答:

0赞 s3c 11/11/2022 #1

您可以使用 Spatie 的 DataCollection 对象:

<?php

namespace App\Data;

use Spatie\LaravelData\Attributes\DataCollectionOf;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;

class Group extends Data
{
    public function __construct(
        public string $id,
        #[DataCollectionOf(Group::class)]
        public DataCollection $subGroups,
    ) {
    }
}