Mastering Custom Eloquent Casts in Laravel: A Beginner’s Guide

Author

Kritim Yantra

Jun 15, 2025

Mastering Custom Eloquent Casts in Laravel: A Beginner’s Guide

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 You’ll Learn:

✅ 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


🛠️ What Are Custom Eloquent Casts?

Built-in vs. Custom Casts

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

How It Works

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' }

📦 Creating Your First Custom Cast

Step 1: Generate a Cast Class

Run:

php artisan make:cast MoneyCast

This creates:
app/Casts/MoneyCast.php

Step 2: Define the Cast Logic

<?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;
    }
}

Step 3: Use It in a Model

class Product extends Model
{
    protected $casts = [
        'price' => MoneyCast::class,
    ];
}

Now $product->price returns a Money object instead of a plain number!


💡 Real-World Use Cases

1. Money Handling (Currency + Amount)

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"

2. Phone Number Formatting

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"

3. JSON ↔ Object Conversion

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"

🚀 Advanced Custom Casts

1. Nullable Casts

Handle NULL values gracefully:

public function get($model, $key, $value, $attributes)
{
    return $value ? new Money($value, 'USD') : null;
}

2. Array/JSON Casting

Store arrays as JSON but retrieve as collections:

public function get($model, $key, $value, $attributes)
{
    return collect(json_decode($value, true));
}

3. Dependent Casts (Using Other Attributes)

Example: Store amount and currency separately but cast as Money:

public function get($model, $key, $value, $attributes)
{
    return new Money($value, $attributes['currency'] ?? 'USD');
}

✅ Best Practices

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.


🎯 Key Takeaways

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!


🚀 What’s Next?

  1. Try creating a DateRangeCast (stores start_date + end_date as a single object).
  2. Experiment with 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! 👇

Ajay Yadav

Ajay Yadav

Senior Full-Stack Engineer

7 + Years Experience

Transforming Ideas Into Digital Solutions

I architect and build high-performance web applications with modern tech:

Laravel PHP 8+ Vue.js React.js Flask Python MySQL

Response time: under 24 hours • 100% confidential

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts