Use a custom Eloquent Attribute Cast to hydrate a rich Value Object (or DTO) instead of raw arrays or primitives.
Create a cast class that implements CastsAttributes (or the Castable interface):
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use App\ValueObjects\Money;
class MoneyCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
return new Money((int) $value);
}
public function set($model, string $key, $value, array $attributes)
{
return ['price' => $value instanceof Money
? $value->toCents()
: (int) $value
];
}
}
Register it on your model’s $casts:
class Order extends Model
{
protected $casts = [
'price' => App\Casts\MoneyCast::class,
];
}
Now every time you access →price you get a Money object (with methods for formatting, currency math, etc.), and it’s always serialized back correctly when saving. This cleanly encapsulates logic, ensures type safety, and keeps your models slim.