Kritim Yantra
Jun 15, 2025
Imagine you’re storing phone numbers in your database. By default, Laravel treats them as plain strings. But what if you want to:
✔ Automatically format them (e.g., +1 (123) 456-7890
)?
✔ Validate them before saving?
✔ Convert them into a dedicated PhoneNumber
object?
This is where Custom Eloquent Casts come in!
✅ What are Custom Casts and why they’re useful
✅ How to create your own cast classes
✅ Real-world examples (Money, JSON, Phone Numbers)
✅ Best practices for clean, reusable code
Laravel has built-in casts (int
, bool
, datetime
, etc.), but sometimes you need more control.
Built-in Casts | Custom Casts |
---|---|
'price' => 'integer' |
'price' => MoneyCast::class |
'is_active' => 'boolean' |
'phone' => PhoneNumberCast::class |
'created_at' => 'datetime' |
'address' => AddressCast::class |
When you retrieve data from the database, Laravel transforms it using your custom cast.
When you save data, Laravel reverts it back to a storable format.
Example:
// Database: "price" = 1000 (integer)
// After casting: Money { amount: 1000, currency: 'USD' }
Run:
php artisan make:cast MoneyCast
This creates:app/Casts/MoneyCast.php
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class MoneyCast implements CastsAttributes
{
// Transform raw DB value → Useful object
public function get($model, $key, $value, $attributes)
{
return new Money($value, 'USD'); // Example: Money object
}
// Transform object → Storable DB value
public function set($model, $key, $value, $attributes)
{
return $value instanceof Money ? $value->amount : $value;
}
}
class Product extends Model
{
protected $casts = [
'price' => MoneyCast::class,
];
}
Now $product->price
returns a Money
object instead of a plain number!
Problem: Storing 1000
in the DB doesn’t tell us if it’s USD, EUR, or JPY.
Solution:
// app/Casts/MoneyCast.php
public function get($model, $key, $value, $attributes)
{
return new Money($value, 'USD'); // Converts 1000 → Money(1000, 'USD')
}
public function set($model, $key, $value, $attributes)
{
return $value instanceof Money ? $value->amount : $value;
}
Usage:
$product = Product::find(1);
echo $product->price->formatted(); // "$10.00"
Problem: Storing raw 1234567890
but displaying as (123) 456-7890
.
Solution:
// app/Casts/PhoneNumberCast.php
public function get($model, $key, $value, $attributes)
{
return new PhoneNumber($value); // Formats the number
}
public function set($model, $key, $value, $attributes)
{
return preg_replace('/[^0-9]/', '', $value); // Saves as digits only
}
Usage:
$user = User::find(1);
echo $user->phone; // "(123) 456-7890"
Problem: Storing { "street": "123 Main St", "city": "NY" }
but working with an Address
object.
Solution:
// app/Casts/AddressCast.php
public function get($model, $key, $value, $attributes)
{
return new Address(json_decode($value, true));
}
public function set($model, $key, $value, $attributes)
{
return json_encode($value);
}
Usage:
$user = User::find(1);
echo $user->address->city; // "NY"
Handle NULL
values gracefully:
public function get($model, $key, $value, $attributes)
{
return $value ? new Money($value, 'USD') : null;
}
Store arrays as JSON but retrieve as collections:
public function get($model, $key, $value, $attributes)
{
return collect(json_decode($value, true));
}
Example: Store amount
and currency
separately but cast as Money
:
public function get($model, $key, $value, $attributes)
{
return new Money($value, $attributes['currency'] ?? 'USD');
}
✔ Keep Casts Small – They should only transform data, not contain business logic.
✔ Reuse Casts – Apply the same MoneyCast
across multiple models.
✔ Test Casts – Ensure get
and set
work correctly.
✔ Custom casts transform data between DB and PHP objects.
✔ Use cases: Money, Phone Numbers, JSON ↔ Objects, and more.
✔ Generate casts via php artisan make:cast
.
✔ Works with Eloquent seamlessly – no extra code needed!
DateRangeCast
(stores start_date
+ end_date
as a single object). EncryptedCast
(auto-encrypt sensitive data).Custom casts make your Eloquent models smarter and more powerful. Start using them today!
💬 Discussion Time!
Have you used custom casts before? What cool transformations have you built? Share below! 👇
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google