CastWith
The CastWith
attribute allows you to automatically cast values during DTO hydration. It supports casting to DTOs, primitive types, enums, and custom types.
Casting to DTOs
Automatically cast a property into a specific DTO (or array of DTOs):
use Alamellama\Carapace\Attributes\CastWith;
final class Account extends ImmutableDTO
{
public function __construct(
public string $name,
#[CastWith(User::class)]
/** @var User[] */
public array $users,
) {}
}
$account = Account::from([
'name' => 'Me, Myself and I',
'users' => [
['name' => 'John', 'email' => 'john@example.com'],
['name' => 'Jane', 'email' => 'jane@example.com'],
],
]);
Important: The
@var
is to help IDEs understand the type of themembers
property. Carapace will automatically cast each using theCastWith
item in the array to the specified DTO type.
Primitive Type Casting
Cast values to primitive types using the PrimitiveCaster
:
use Alamellama\Carapace\Attributes\CastWith;
use Alamellama\Carapace\Casters\PrimitiveCaster;
final class Product extends ImmutableDTO
{
public function __construct(
public string $name,
#[CastWith(new PrimitiveCaster('int'))]
public int $price,
#[CastWith(new PrimitiveCaster('bool'))]
public bool $inStock,
#[CastWith(new PrimitiveCaster('array'))]
public array $tags,
) {}
}
$product = Product::from([
'name' => 'Awesome Product',
'price' => '1299', // String will be cast to int
'inStock' => 1, // Integer will be cast to bool
'tags' => '["sale", "new"]', // JSON string will be cast to array
]);
// You can also pass scalar values to be wrapped in an array
$product = Product::from([
'name' => 'Awesome Product',
'price' => 1299,
'inStock' => true,
'tags' => 'featured', // Will become ['featured']
]);
The PrimitiveCaster
supports the following types:
int
: Casts to integerfloat
: Casts to floatstring
: Casts to stringbool
: Casts to booleanarray
: Handles multiple scenarios:- Keeps arrays as-is
- Converts JSON strings to arrays
- Converts objects to arrays
- Wraps scalar values in an array
Enum Casting
The EnumCaster
allows you to cast values to native PHP enums (both backed and unit enums):
use Alamellama\Carapace\Attributes\CastWith;
use Alamellama\Carapace\Casters\EnumCaster;
use Alamellama\Carapace\ImmutableDTO;
// Define your enums
enum Status: string
{
case PENDING = 'pending';
case ACTIVE = 'active';
case INACTIVE = 'inactive';
}
enum Color
{
case RED;
case GREEN;
case BLUE;
}
// Use EnumCaster in your DTO
final class Task extends ImmutableDTO
{
public function __construct(
public string $title,
#[CastWith(new EnumCaster(Status::class))]
public Status $status,
#[CastWith(new EnumCaster(Color::class))]
public Color $color
) {}
}
// The EnumCaster will handle the conversion
$task = Task::from([
'title' => 'Complete documentation',
'status' => 'active', // String value for backed enum
'color' => 'RED', // Case name for unit enum
]);
// Case-insensitive matching is supported
$task = Task::from([
'title' => 'Complete documentation',
'status' => 'ACTIVE', // Will match Status::ACTIVE
'color' => 'red', // Will match Color::RED
]);
// You can also use enum instances directly
$task = Task::from([
'title' => 'Complete documentation',
'status' => Status::PENDING,
'color' => Color::BLUE,
]);
DateTime Casting
The DateTimeCaster
allows you to automatically cast values to PHP's native DateTime
objects during DTO hydration:
use Alamellama\Carapace\Attributes\CastWith;
use Alamellama\Carapace\Casters\DateTimeCaster;
use Alamellama\Carapace\ImmutableDTO;
final class Event extends ImmutableDTO
{
public function __construct(
public string $name,
#[CastWith(new DateTimeCaster)]
public DateTimeInterface $createdAt,
#[CastWith(new DateTimeCaster('Y-m-d'))]
public DateTimeInterface $eventDate,
) {}
}
$event = Event::from([
'name' => 'Conference',
'createdAt' => '2025-08-04 13:25:00', // Default format: Y-m-d H:i:s
'eventDate' => '2025-10-15', // Custom format: Y-m-d
]);
echo $event->createdAt->format('F j, Y'); // August 4, 2025
echo $event->eventDate->format('F j, Y'); // October 15, 2025
Supported Input Types
The DateTimeCaster
can handle various input types:
- DateTime objects: Passed through unchanged
- Strings: Parsed according to the specified format
- Integers: Treated as Unix timestamps
When working with string dates, you can specify a custom format in the constructor:
// Default format (Y-m-d H:i:s)
#[CastWith(new DateTimeCaster)]
public DateTimeInterface $timestamp;
// Custom format
#[CastWith(new DateTimeCaster('Y-m-d'))]
public DateTimeInterface $date;
If a string doesn't match the specified format, the caster will attempt to parse it using PHP's flexible date parsing capabilities. If that fails, an InvalidArgumentException
will be thrown.
Integer values are treated as Unix timestamps:
$event = Event::from([
'name' => 'Conference',
'createdAt' => 1722945900, // Unix timestamp
'eventDate' => '2025-10-15',
]);
Custom Casters
For information on creating your own custom casters, see the Custom Casters guide in the Advanced section.