adding an enum cast is not only a model change. It changes what the rest of the application receives, so comparisons, forms, services, and tests must all agree on the new type.
Why it happens
A backed PHP enum stores a simple value such as a string or integer, but represents that value in code as a typed enum case. Laravel can convert a database column to that enum automatically with an Eloquent cast.
This removes repeated string checks and makes invalid states harder to introduce. The catch is that code which previously received a raw string may now receive an enum object.
A safe way to add the cast
- Inspect the enum first. Confirm its backing type, cases, and any UI interfaces it already implements. Avoid rewriting an enum that is already compatible with the admin framework.
- Add the model cast. Map the database column to the enum class in the model’s cast configuration.
- Find every consumer. Search for comparisons, conditionals, form fields, query filters, API resources, and publishing or export services that use the column.
-
Update comparisons. Compare the property with an enum case when working with a hydrated model. Use the case’s backed value only where a scalar is required.
-
Verify both directions. Test reading the model, assigning an enum case, saving it, and serializing it.
Example
enum DeliveryMode: string
{
case Manual = 'manual';
case Automatic = 'automatic';
}
Inside the Eloquent model, add:
protected function casts(): array
{
return [
'delivery_mode' => DeliveryMode::class,
];
}
After this cast, a hydrated model property should be compared like this:
if ($record->delivery_mode === DeliveryMode::Automatic) {
// Run automatic delivery.
}
When another system needs a string, use the backed value explicitly:
$payload['delivery_mode'] = $record->delivery_mode->value;
Common mistakes and fixes
- Cause: comparing the cast property to a raw string. Fix: compare it to the enum case.
-
Cause: rewriting an enum before checking its existing capabilities. Fix: inspect the enum and add only the missing integration.
-
Cause: testing only syntax. Fix: verify database hydration and scalar serialization too.
-
Cause: changing unrelated formatting while making a small type-safety fix. Fix: keep the patch narrow so review remains clear.
Check existing values before enabling the cast
Inspect distinct stored values and nullable rows first. A backed enum cannot represent an arbitrary legacy string, and invalid values can fail during hydration. Decide how to migrate invalid data before deployment. If the column is nullable, handle null before reading ->value, for example with $record->delivery_mode?->value when a nullable payload is intended.
Enum casting is valuable because it moves domain rules into the type system. The safe approach is to treat it as an application-wide contract change, not a one-line model edit.
Next action: before adding an enum cast, search for every read, comparison, and exported value of that column.
Reference: Laravel enum casting.
