Skip to content

Type Casting

Learn how SimpleDTO automatically converts data types using built-in and custom casts.

Type casting automatically converts input data to the correct PHP type. For example:

// Input: string "30"
// Output: int 30
// Input: string "2024-01-15"
// Output: Carbon instance

SimpleDTO provides 20+ built-in casts for common data types.

class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name, // String cast
public readonly int $age, // Integer cast
public readonly float $price, // Float cast
public readonly bool $active, // Boolean cast
public readonly array $tags, // Array cast
) {}
}
$dto = UserDTO::fromArray([
'name' => 123, // → "123"
'age' => "30", // → 30
'price' => "19.99", // → 19.99
'active' => "1", // → true
'tags' => "tag1,tag2", // → ["tag1,tag2"]
]);
use Event4u\DataHelpers\SimpleDTO\Attributes\Cast;
use Event4u\DataHelpers\SimpleDTO\Casts\DateTimeCast;
class EventDTO extends SimpleDTO
{
public function __construct(
public readonly string $title,
#[Cast(DateTimeCast::class)]
public readonly Carbon $startDate,
#[Cast(DateTimeCast::class, format: 'Y-m-d')]
public readonly Carbon $endDate,
) {}
}
$dto = EventDTO::fromArray([
'title' => 'Conference',
'startDate' => '2024-01-15 10:00:00',
'endDate' => '2024-01-15',
]);
echo $dto->startDate->format('F j, Y'); // January 15, 2024
use Event4u\DataHelpers\SimpleDTO\Casts\DateCast;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[Cast(DateCast::class)]
public readonly Carbon $birthDate,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'John Doe',
'birthDate' => '1990-05-15',
]);
use Event4u\DataHelpers\SimpleDTO\Attributes\Cast;
use Event4u\DataHelpers\SimpleDTO\Casts\EnumCast;
enum Status: string
{
case ACTIVE = 'active';
case INACTIVE = 'inactive';
case PENDING = 'pending';
}
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[Cast(EnumCast::class)]
public readonly Status $status,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'John Doe',
'status' => 'active', // String → Status::ACTIVE
]);
echo $dto->status->value; // active
enum Priority: int
{
case LOW = 1;
case MEDIUM = 2;
case HIGH = 3;
}
class TaskDTO extends SimpleDTO
{
public function __construct(
public readonly string $title,
#[Cast(EnumCast::class)]
public readonly Priority $priority,
) {}
}
$dto = TaskDTO::fromArray([
'title' => 'Important Task',
'priority' => 3, // Int → Priority::HIGH
]);
use Event4u\DataHelpers\SimpleDTO\Casts\ArrayCast;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[Cast(ArrayCast::class)]
public readonly array $tags,
#[Cast(ArrayCast::class, itemType: 'int')]
public readonly array $scores,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'John Doe',
'tags' => 'tag1,tag2,tag3', // String → Array
'scores' => ['10', '20', '30'], // String[] → Int[]
]);
use Event4u\DataHelpers\SimpleDTO\Casts\CollectionCast;
class OrderDTO extends SimpleDTO
{
public function __construct(
public readonly int $orderId,
#[Cast(CollectionCast::class, itemType: OrderItemDTO::class)]
public readonly array $items,
) {}
}
$dto = OrderDTO::fromArray([
'orderId' => 123,
'items' => [
['product' => 'Widget', 'quantity' => 2],
['product' => 'Gadget', 'quantity' => 1],
],
]);
use Event4u\DataHelpers\SimpleDTO\Casts\ObjectCast;
class AddressDTO extends SimpleDTO
{
public function __construct(
public readonly string $street,
public readonly string $city,
) {}
}
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[Cast(ObjectCast::class, type: AddressDTO::class)]
public readonly AddressDTO $address,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'John Doe',
'address' => [
'street' => '123 Main St',
'city' => 'New York',
],
]);
use Event4u\DataHelpers\SimpleDTO\Casts\EncryptedCast;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[Cast(EncryptedCast::class)]
public readonly string $ssn,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'John Doe',
'ssn' => '123-45-6789', // Encrypted when stored
]);
// Automatically decrypted when accessed
echo $dto->ssn; // 123-45-6789
use Event4u\DataHelpers\SimpleDTO\Contracts\Cast;
class UpperCaseCast implements Cast
{
public function cast(mixed $value): mixed
{
return strtoupper($value);
}
public function uncast(mixed $value): mixed
{
return strtolower($value);
}
}
class UserDTO extends SimpleDTO
{
public function __construct(
#[Cast(UpperCaseCast::class)]
public readonly string $name,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'john doe', // → "JOHN DOE"
]);
class TruncateCast implements Cast
{
public function __construct(
private int $length = 100
) {}
public function cast(mixed $value): mixed
{
return substr($value, 0, $this->length);
}
public function uncast(mixed $value): mixed
{
return $value;
}
}
class PostDTO extends SimpleDTO
{
public function __construct(
#[Cast(TruncateCast::class, length: 50)]
public readonly string $title,
) {}
}
CastDescriptionExample
StringCastConvert to string123"123"
IntegerCastConvert to integer"30"30
FloatCastConvert to float"19.99"19.99
BooleanCastConvert to boolean"1"true
ArrayCastConvert to array"a,b"["a","b"]
DateTimeCastConvert to Carbon"2024-01-15"Carbon
DateCastConvert to Carbon (date only)"2024-01-15"Carbon
EnumCastConvert to enum"active"Status::ACTIVE
ObjectCastConvert to object[...]AddressDTO
CollectionCastConvert to collection[...]Collection
JsonCastParse JSON"{...}"array
EncryptedCastEncrypt/decrypt"secret" → encrypted
HashCastHash value"password" → hashed
UrlCastValidate URL"example.com""https://example.com"
EmailCastNormalize email"JOHN@EXAMPLE.COM""john@example.com"
PhoneCastFormat phone"1234567890""+1 (234) 567-8900"
MoneyCastFormat money1999"$19.99"
PercentageCastFormat percentage0.15"15%"
SlugCastCreate slug"Hello World""hello-world"
UuidCastValidate UUID"..." → UUID
#[Cast(DateTimeCast::class, format: 'Y-m-d H:i:s')]
public readonly Carbon $createdAt;
#[Cast(DateTimeCast::class, nullable: true)]
public readonly ?Carbon $deletedAt;
#[Cast(IntegerCast::class, default: 0)]
public readonly int $count;
// ✅ Good - explicit cast
#[Cast(DateTimeCast::class)]
public readonly Carbon $createdAt;
// ❌ Bad - relying on type hint only
public readonly Carbon $createdAt;
// ✅ Good - explicit format
#[Cast(DateTimeCast::class, format: 'Y-m-d')]
public readonly Carbon $date;
// ❌ Bad - ambiguous format
#[Cast(DateTimeCast::class)]
public readonly Carbon $date;
// ✅ Good
#[Cast(DateTimeCast::class, nullable: true)]
public readonly ?Carbon $deletedAt;
// ❌ Bad
#[Cast(DateTimeCast::class)]
public readonly ?Carbon $deletedAt;

The following working examples demonstrate this feature:

All examples are fully tested and can be run directly.

The functionality is thoroughly tested. Key test files:

Run the tests:

Terminal window
# Run tests
task test:unit -- --filter=Cast