Menü schliessen
Created: March 31st 2025
Categories: IT Development,  Laravel
Author: Nikola Jevtic

Eloquent Casts in Laravel: Go Beyond the Basics with Custom Data Transformation

Donation Section: Background
Monero Badge: QR-Code
Monero Badge: Logo Icon Donate with Monero Badge: Logo Text
82uymVXLkvVbB4c4JpTd1tYm1yj1cKPKR2wqmw3XF8YXKTmY7JrTriP4pVwp2EJYBnCFdXhLq4zfFA6ic7VAWCFX5wfQbCC

Using Eloquent Casts Beyond Basics

Introduction

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.


What Are Eloquent Casts?

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.

Basic Example

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 Attribute Casting with [CastsAttributes]

Custom casts let you define how a model transforms attributes when saving to or reading from the database.

Creating a Custom Cast

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

Usage in Model

protected $casts = [
    'password' => \App\Casts\HashCast::class,
];

Casting Value Objects

Laravel supports casting attributes into Value Objects using [CastsAttributes], or better, using DTO-like data structures.

Example: Money Value Object

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.


Built-In Caster Classes

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.


Enum Casting

You can cast attributes directly to native PHP [enum] types (PHP 8.1+).

Example: UserStatus Enum

namespace App\Enums;

enum UserStatus: string {
    case Active = 'active';
    case Inactive = 'inactive';
}

Usage in Model

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.


When to Use Advanced Casts

Use advanced casting when:

  • Working with structured, complex data.
  • You want to encapsulate transformation logic.
  • You aim for reusability across multiple models.
  • Enums or value objects make domain logic clearer.

Avoid if:

  • You only need minor formatting (use accessors).
  • You need dynamic behavior based on other attributes.

Conclusion

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.