We extend our example data object just a little bit:
class SongData extends Data
{
public function __construct(
public string $title,
public string $artist,
public DateTime $date,
public Format $format,
) {
}
}
The Format
property here is an Enum
from our enum package and looks like this:
class Format extends Enum{
}
When we now try to construct a data object like this:
SongData::from([
'title' => 'Never gonna give you up',
'artist' => 'Rick Astley',
'date' => '27-07-1987',
'format' => 'vinyl',
]);
And get an error because the first two properties are simple PHP types(string, int's, floats, booleans, arrays), but the following two properties are more complex types: DateTime
and Enum
, respectively.
These types cannot be automatically created. A cast is needed to construct them from a string.
There are two types of casts, local and global casts.
##Local casts
Local casts are defined within the data object itself and can be added using attributes:
class SongData extends Data
{
public function __construct(
public string $title,
public string $artist,
#[WithCast(DateTimeInterfaceCast::class)]
public DateTime $date,
#[WithCast(EnumCast::class)]
public Format $format,
) {
}
}
Now it is possible to create a data object like this without exceptions:
SongData::from([
'title' => 'Never gonna give you up',
'artist' => 'Rick Astley',
'date' => '27-07-1987',
'format' => 'vinyl',
]);
It is possible to provide parameters to the casts like this:
#[WithCast(EnumCast::class, class: Format::class)]
public Format $format
##Casting dates
By default, the package ships with a DateTimeInterface
cast to transform a date string into a date object. You can define the format used to parse the date in the data.php
config file. By default, it is the DATE_ATOM
format.
It is also possible to manually set the format on the cast:
#[WithCast(DateTimeInterfaceCast::class, format: DATE_ATOM)]
public DateTime $date
The data object will use the type of the property to cast a date string into, so if you want to use Carbon
, that's perfectly possible:
#[WithCast(DateTimeInterfaceCast::class)]
public Carbon $date
You can even manually specify the type the date string should be cast to:
#[WithCast(DateTimeInterfaceCast::class, type: CarbonImmutable::class)]
public $date
##Global casts
Global casts are not defined on the data object but in your data.php
config file:
'casts' => [
DateTimeInterface::class => Spatie\LaravelData\Casts\DateTimeInterfaceCast::class,
],
When the data object can find no local cast for the property, the package will look through the global casts and tries to find a suitable cast. You can define casts for:
- a specific implementation (e.g. CarbonImmutable)
- an interface (e.g. DateTimeInterface)
- a base class (e.g. Enum)
As you can see, the package by default already provides a DateTimeInterface
cast, this means we can update our data object like this:
class SongData extends Data
{
public function __construct(
public string $title,
public string $artist,
public DateTime $date,
#[WithCast(EnumCast::class)]
public Format $format,
) {
}
}
##Creating your own casts
It is possible to create your casts. You can read more about this in the advanced chapter.