Implement the CastsAttributes interface to create reusable custom value object casts for Eloquent model attributes.
When database columns store custom structures (such as storing monetary amounts in cents, encrypted payloads, or coordinate objects), converting them manually in accessors and mutators across models creates duplicate logic.
Custom Cast classes encapsulate two-way transformation logic cleanly.
Generating a Custom Cast
php artisan make:cast MoneyCast
Implementing CastsAttributes
namespace App\Casts;
use App\ValueObjects\Money;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
class MoneyCast implements CastsAttributes
{
public function get(Model $model, string $key, mixed $value, array $attributes): ?Money
{
return $value !== null ? new Money((int) $value) : null;
}
public function set(Model $model, string $key, mixed $value, array $attributes): ?int
{
return $value instanceof Money ? $value->getAmountInCents() : $value;
}
}
Applying to Models
namespace App\Models;
use App\Casts\MoneyCast;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $casts = [
'price' => MoneyCast::class,
];
}
Summary
- Encapsulates bi-directional serialization (
getfrom DB,setto DB). - Turns raw database integers and strings into rich Value Objects.
- Reusable across all application models.
Related Tips
View all tips →Avoid Redundant Eloquent Overrides by Embracing Convention over Configuration
Remove unnecessary $table, $primaryKey, and $timestamps properties from Eloquent models by adhering to standard Laravel conventions.
Scope Pivot Table Queries with Closures in wherePivot() in Laravel 13.26
Laravel 13.26 allows wherePivot() and orWherePivot() to accept closures, enabling direct reuse of local scopes defined on custom Pivot models.