Cast enum instances nested within JSON or array database columns using Eloquent Attribute accessors and mutators.
Laravel provides first-party enum casting for standard model columns:
protected $casts = [
'status' => PostStatus::class,
];
However, when an enum value is stored inside a nested JSON object or array column (such as options->status or settings['status']), Laravel's default column casting casts the entire column to an array, leaving the nested enum value as a raw string or integer.
Using Eloquent's Attribute accessor and mutator, you can automatically hydrate and serialize nested enum instances.
Implementing the Nested Enum Cast
namespace App\Models;
use App\Enums\PostStatus;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected function options(): Attribute
{
return Attribute::make(
get: function ($value): array {
$options = json_decode($value ?? '[]', true) ?? [];
// Hydrate string value to Backed Enum instance
if (isset($options['status'])) {
$options['status'] = PostStatus::tryFrom($options['status']) ?? $options['status'];
}
return $options;
},
set: function ($value): string {
$options = is_array($value) ? $value : (json_decode($value, true) ?? []);
// Serialize Backed Enum instance to scalar value before storing
if (isset($options['status']) && $options['status'] instanceof PostStatus) {
$options['status'] = $options['status']->value;
}
return json_encode($options);
}
);
}
}
Practical Usage
You can now interact with nested enum properties as strongly typed objects:
$post = Post::find(1);
// Accessing the nested enum
if ($post->options['status'] === PostStatus::Draft) {
// Strongly typed enum comparison
}
// Updating the nested enum
$options = $post->options;
$options['status'] = PostStatus::Published;
$post->options = $options;
$post->save();
Summary
- Use Eloquent
Attribute::make()to hydrate and serialize enums nested inside JSON attributes. - Use
PostStatus::tryFrom()in the getter to gracefully handle unexpected values without throwing exceptions. - Ensures strongly typed enum consistency even for schemaless or flexible JSON payloads.
Related Tips
View all tips →Combine Custom Casts and Enums for Complex Attributes
Use Eloquent custom casts (CastsAttributes) to handle complex JSON serialization and Backed Enum arrays cleanly.
Define Custom Macros on the Eloquent Builder
Register reusable query methods directly on the Builder so every model gains access without repeating logic.