phprestdtodata-transfer-objects

PHP Spatie DTOs with sub arrays


I'm trying to implement an endpoint for the Audd audio detection API (callback with a result), using Spatie's Data Transfer Object package for PHP. For this, I have a PlayDTO, which has a PlayResultDTO attribute, which in turn should have an array of PlayTrackDTOs as a sub-attribute:

// PlayDTO.php
namespace App\DTO\Play;
use Spatie\DataTransferObject\DataTransferObject;

class PlayDTO extends DataTransferObject
{
    public string $status;
    public PlayResultDTO $result;
}

//PlayResultDTO.php
namespace App\DTO\Play;
use Spatie\DataTransferObject\DataTransferObject;
class PlayResultDTO extends DataTransferObject
{
    public int $radio_id;
    public string $timestamp;
    public int $play_length;
    /** @var PlayTrackDTO[] */
    #[CastWith(ArrayCaster::class, itemType: PlayTrackDTO::class)]
    public array $results;
}

// PlayTrackDTO.php
namespace App\DTO\Play;
use Spatie\DataTransferObject\DataTransferObject;
class PlayTrackDTO extends DataTransferObject
{
    public string $artist;
    public string $title;
    public string $album;
    public string $release_date;
    public string $label;
    public int $score;
    public string $song_link;
}

When I pass a valid array of data to my PlayDTO constructor, in the newly instaitated PlayDTO class, $result correctly has type PlayResultDTO, but in that $result it's $results attribute is just a simple array of keyed-arrays, when it should be an array of PlayTrackDTO objects.

As far as I can see I followed the guide correctly. I have the most up to date version of the package installed, as well as using PHP8. Would anyone have any suggestions? Thanks


Solution

  • You need to use the CastWith class form Spatie Attributes. Also, you are using ArrayCaster, so you need to use that as well.

    use Spatie\DataTransferObject\Casters\ArrayCaster;
    use Spatie\DataTransferObject\Attributes\CastWith;