Nested & Collection Data
Data objects compose. A property typed as another Data class is recursively
hydrated and serialized.
Nested data
class AddressData extends Data
{
public function __construct(
public string $street,
public string $city,
) {}
}
class UserData extends Data
{
public function __construct(
public string $name,
public AddressData $address,
) {}
}
$user = UserData::from([
'name' => 'Ada',
'address' => ['street' => '1 Main St', 'city' => 'London'],
]);
$user->address; // AddressData instance
$user->toArray();
// ['name' => 'Ada', 'address' => ['street' => '1 Main St', 'city' => 'London']]
The nested address array is automatically turned into an AddressData.
Arrays of data
Use #[ArrayOf] (or a @var array<…, Type> phpdoc) to hydrate every element of
an array:
use BradieTilley\Data\Attributes\ArrayOf;
class TeamData extends Data
{
public function __construct(
public string $name,
#[ArrayOf(UserData::class)]
public array $members,
) {}
}
TeamData::from([
'name' => 'Core',
'members' => [
['name' => 'Ada', 'address' => ['street' => '…', 'city' => '…']],
['name' => 'Alan', 'address' => ['street' => '…', 'city' => '…']],
],
]);
// members is a list of hydrated UserData
Non-Data element types (e.g. DateTime, backed enums, Carbon) are cast the same
way a scalar property of that type would be:
#[ArrayOf(DateTime::class)]
public array $releaseDates;
#[ArrayOf('string')]
public Collection $tags;
The same mechanism casts arrays of custom value objects via
IterableItemCast:
class ReleaseData extends Data
{
public function __construct(
public string $title,
/**
* @var array<int, DateTime>
*/
public array $releaseDates,
) {}
}
Collections of data
When Laravel is installed, a property typed Illuminate\Support\Collection with
#[ArrayOf] hydrates into a Collection of items:
use Illuminate\Support\Collection;
class TeamData extends Data
{
public function __construct(
#[ArrayOf(UserData::class)]
public Collection $members,
) {}
}
Collecting many at once
Data::collect() maps an iterable of inputs into many Data instances:
$people = UserData::collect([
['name' => 'Ada', 'address' => [...]],
['name' => 'Alan', 'address' => [...]],
]);
- With Laravel installed,
collect()returns anIlluminate\Support\Collection. - Without Laravel, it returns a plain
array— see Framework-agnostic usage.