Laravel’s Eloquent ORM is beloved for its elegance—but model casting has long been a pain point. From cryptic syntax to limited flexibility, the old $casts array often felt like a bottleneck.
Laravel 12 changes the game with a new casts() method that makes casting smarter, cleaner, and more expressive.
Let’s break down the problem, the fix, and how to use it like a pro.
😵 The Problem with $casts
Traditionally, Laravel developers defined model casts using the $casts array:
protected $casts = [
'email_verified_at' => 'datetime',
'options' => AsEnumCollection::class . ':' . UserOption::class,
];
But this approach had serious limitations:
- No static method calls: You couldn’t use expressive caster methods like
AsEnumCollection::of(...). - String-based syntax: Complex casts required awkward concatenation or custom parsing.
- Limited IDE support: Type inference and autocomplete struggled with string-based definitions.
- No dynamic logic: You couldn’t conditionally define casts based on runtime context.
✅ The Fix: Laravel 12’s casts() Method
Laravel 12 introduces a new casts() method that replaces (or complements) the $casts array with a fluent, expressive approach:
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
use App\Enums\UserOption;
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'options' => AsEnumCollection::of(UserOption::class),
];
}
🔥 Key Benefits:
- Static method support: Use built-in caster methods like
of(),using(), etc. - Cleaner syntax: No more string concatenation or colon hacks.
- Better IDE support: Type-safe, autocompletable, and easier to debug.
- Override-friendly: The
casts()method takes precedence over$castsif both are defined.
🧪 Real-World Example: Enum Collections
Let’s say you’re storing user preferences as an enum collection. With the new method:
use App\Enums\UserOption;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
protected function casts(): array
{
return [
'preferences' => AsEnumCollection::of(UserOption::class),
];
}
This is cleaner, safer, and more readable than the old string-based approach.
🧙♂️ Advanced Caster Enhancements
Laravel 12 also introduces new static methods on built-in casters:
AsCollection::using(OptionCollection::class);
AsEncryptedCollection::using(OptionCollection::class);
AsEnumArrayObject::using(OptionEnum::class);
These methods let you customize how collections, encrypted data, and enums are cast—without writing custom cast classes.
🧠 Migration Strategy
Laravel 12 is backward-compatible. You can still use $casts if needed, but here’s how to migrate:
- Move definitions from
$caststocasts()method. - Replace string-based casters with fluent static methods.
- Test edge cases—especially custom castables and encrypted fields.
- Use IDE tools to refactor and validate type safety.
💡 Developer Tips
- Prefer
casts()for new models—it’s future-proof and more expressive. - Use static methods like
of()andusing()to simplify complex casts. - Combine with value objects and custom castables for rich domain modeling.
- Document your casts for clarity—especially when using enums or encrypted fields.
🔮 Final Thoughts
Laravel 12’s casts() method is more than a syntax tweak—it’s a DX upgrade that solves real-world pain points. It empowers developers to write cleaner, safer, and more maintainable Eloquent models.
If you’ve ever cursed the $casts array, this is your moment of redemption.
