Could we help you? Please click the banners. We are young and desperately need the money
Laravel’s Eloquent ORM is known for its elegant syntax and powerful features. One of those features — often used but rarely mastered — is attribute casting. With basic casts, you can easily convert JSON strings to arrays or format dates. But there’s much more power under the hood.
In this post, we’ll go beyond the basics of Eloquent casts, exploring custom casts, value object casting, and casting complex data structures, all while keeping our Laravel models clean, expressive, and optimized.
Attribute casting allows you to automatically convert model attributes to and from common data types.
This can simplify working with JSON, dates, booleans, and more.
protected $casts = [ 'is_active' => 'boolean', 'settings' => 'array', 'created_at' => 'datetime:Y-m-d', ];
These simple casts make data manipulation easier, but Laravel offers much deeper capabilities.
Custom casts let you define how a model transforms attributes when saving to or reading from the database.
php artisan make:cast HashCast --- namespace App\Casts; use Illuminate\Contracts\Database\Eloquent\CastsAttributes; use Illuminate\Support\Facades\Hash; class HashCast implements CastsAttributes { public function get($model, string $key, $value, array $attributes) { return $value; } public function set($model, string $key, $value, array $attributes) { return Hash::make($value); } }
protected $casts = [ 'password' => \App\Casts\HashCast::class, ];
Laravel supports casting attributes into Value Objects using [CastsAttributes], or better, using DTO-like data structures.
Let’s say you want to store monetary values in your database as JSON, but work with them in your application as structured [Money] objects.
1. Define the Value Object
namespace App\ValueObjects; class Money { public int $amount; public string $currency; public function __construct(int $amount, string $currency) { $this->amount = $amount; $this->currency = $currency; } public function __toString(): string { return "{$this->amount} {$this->currency}"; } }
2. Create the Cast Class
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): Money { $data = json_decode($value, true); return new Money($data['amount'], $data['currency']); } public function set($model, string $key, $value, array $attributes): string { return json_encode([ 'amount' => $value->amount, 'currency' => $value->currency, ]); } }
3. Apply to Your Model
protected $casts = [ 'price' => \App\Casts\MoneyCast::class, ];
Now, whenever you access the [price] attribute on your model, it will be an instance of [Money]. When saving, it will automatically be converted to a JSON string.
Laravel offers convenient built-in casters for structured data:
1. AsArrayObject
protected $casts = [ 'config' => AsArrayObject::class, ];
Stores and retrieves config as a ArrayObject instance.
2. AsCollection
protected $casts = [ 'tags' => AsCollection::class, ];
Automatically converts to a Laravel Collection.
These help encapsulate logic without creating your own classes.
You can cast attributes directly to native PHP [enum] types (PHP 8.1+).
namespace App\Enums; enum UserStatus: string { case Active = 'active'; case Inactive = 'inactive'; }
use App\Enums\UserStatus; protected $casts = [ 'status' => UserStatus::class, ];
This keeps your domain logic expressive and type-safe.
When a [User] model is retrieved from the database, the [status] field will automatically be cast into a [UserStatus] enum instance:
$user = User::find(1); echo $user->status->value; // "active"
When saving, you can assign it like this:
$user->status = UserStatus::Inactive; $user->save();
This allows you to avoid string comparisons and ensures type safety throughout your app.
Laravel’s casting system goes far beyond just booleans and arrays. With custom casting, enum integration, and value objects, you can write clean, expressive, and reusable logic that keeps your Eloquent models elegant.
If you're not using advanced casts yet, you're likely writing more boilerplate code than necessary. Give them a try — your models will thank you.