Custom Casters
Carapace ships with several built‑in casters and also lets you provide your own by implementing CasterInterface
. Custom casters are used via the CastWith attribute during the hydration stage.
Creating a Custom Caster
Implement the CasterInterface
from Alamellama\Carapace\Contracts
.
php
use Alamellama\Carapace\Contracts\CasterInterface;
class MyCaster implements CasterInterface
{
public function cast(mixed $value): mixed
{
// Validate input and transform
if ($value === null) {
// Let CastWith handle nulls based on property type; usually return null as-is
return null;
}
// ... your casting logic
$transformed = $value; // replace with real logic
return $transformed;
}
}
TIP
Throw InvalidArgumentException
for unsupported inputs. CastWith will surface helpful error messages.
Example: Carbon date caster
Here's an example of a custom caster for Carbon dates:
php
use Alamellama\Carapace\Contracts\CasterInterface;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use DateTimeInterface;
use InvalidArgumentException;
final class CarbonCaster implements CasterInterface
{
public function __construct(
private string $format = 'Y-m-d H:i:s'
) {}
public function cast(mixed $value): CarbonInterface
{
if ($value instanceof CarbonInterface) {
return $value;
}
if ($value instanceof DateTimeInterface) {
return Carbon::instance($value);
}
if (is_string($value)) {
// Try explicit format first
$carbon = Carbon::createFromFormat($this->format, $value);
if ($carbon !== false) {
return $carbon;
}
// Fallback to flexible parser
return Carbon::parse($value);
}
if (is_int($value)) {
return Carbon::createFromTimestamp($value);
}
throw new InvalidArgumentException('Cannot cast to Carbon: unsupported type ' . gettype($value));
}
}
Using your caster with CastWith
CastWith accepts one of the following:
- A DTO class‑string (e.g. User::class) — arrays/objects/JSON will be cast to that DTO, lists to arrays of DTOs
- A caster class‑string (e.g. PrimitiveCaster::class) — CastWith will instantiate it with no arguments
- A caster instance (e.g. new PrimitiveCaster('int'))
php
use Alamellama\Carapace\Attributes\CastWith;
use Alamellama\Carapace\Data;
use Carbon\CarbonInterface;
final class Event extends Data
{
public function __construct(
public string $name,
// Pass an instance when your caster has constructor args
#[CastWith(new CarbonCaster('Y-m-d'))]
public CarbonInterface $date,
) {}
}
$event = Event::from([
'name' => 'Conference',
'date' => '2025-08-15', // Will be cast to Carbon
]);