> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/spatie/laravel-data/llms.txt
> Use this file to discover all available pages before exploring further.

# Casts

> Transform data types using local and global casts for complex types like DateTime, Enums, and custom types.

We extend our example data object just a little bit:

```php theme={null}
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` and looks like this:

```php theme={null}
enum Format: string {
    case cd = 'cd';
    case vinyl = 'vinyl';
    case cassette = 'cassette';
}
```

When we now try to construct a data object like this:

```php theme={null}
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 (strings, ints, 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:

```php theme={null}
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:

```php theme={null}
SongData::from([
    'title' => 'Never gonna give you up',
    'artist' => 'Rick Astley',
    'date' => '27-07-1987',
    'format' => 'vinyl',
]);
```

### Cast Parameters

It is possible to provide parameters to the casts like this:

```php theme={null}
#[WithCast(EnumCast::class, type: Format::class)]
public Format $format
```

## Global Casts

Global casts are not defined on the data object but in your `data.php` config file:

```php theme={null}
'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:

```php theme={null}
class SongData extends Data
{
    public function __construct(
        public string $title,
        public string $artist,
        public DateTime $date,
        #[WithCast(EnumCast::class)]
        public Format $format,
    ) {
    }
}
```

<Tip>
  We can also remove the `EnumCast` since the package will automatically cast enums because they're a native PHP type, but this made the example easy to understand.
</Tip>

## Creating Your Own Casts

It is possible to create your casts. You can read more about this in the [advanced chapter](/advanced-usage/creating-a-cast).

## Casting Arrays or Collections of Non-Data Types

We've already seen how collections of data can be made of data objects, the same is true for all other types if correctly typed.

Let say we have an array of DateTime objects:

```php theme={null}
class ReleaseData extends Data
{
    public string $title;
    /** @var array<int, DateTime> */
    public array $releaseDates;
}
```

By enabling the `cast_and_transform_iterables` feature in the `data` config file (this feature will be enabled by default in laravel-data v5):

```php theme={null}
'features' => [
    'cast_and_transform_iterables' => true,
],
```

We now can create a `ReleaseData` object with an array of strings which will be cast into an array DateTime objects:

```php theme={null}
ReleaseData::from([
    'title' => 'Never Gonna Give You Up',
    'releaseDates' => [
        '1987-07-27T12:00:00Z',
        '1987-07-28T12:00:00Z',
        '1987-07-29T12:00:00Z',
    ],
]);
```

<Note>
  For this feature to work, a cast should not only implement the `Cast` interface but also the `IterableItemCast`. The signatures of the `cast` and `castIterableItem` methods are exactly the same, but they're called on different times. When casting a property like a DateTime from a string, the `cast` method will be used, when transforming an iterable property like an array or Laravel Collection where the iterable item is typed using an annotation, then each item of the provided iterable will trigger a call to the `castIterableItem` method.
</Note>
