Enums were introduced in PHP 8.1, and Laravel now fully embraces them. But using plain enums alone doesn’t take full advantage of what they can offer. In this post, we’ll enhance Laravel enums to make them more powerful, readable, and developer-friendly—with features like:
- Labeling enum values for dropdowns and forms
- Array helpers
- Safe value resolution
- Enum validation
- Model casting
The Problem with Plain Enums
Here’s a basic enum in Laravel:
enum VerificationTypeEnum: string
{
case DRIVER_LICENSE = 'driver-license';
case PASSPORT = 'passport';
// ...
}
While it works, there’s no built-in way to:
- Get all values as an array
- Display readable labels
- Convert user input back to enum safely
- Use in dropdowns or form validation
Let’s fix that.
Full Enum Example with Enhancements
namespace App\Enums;
enum VerificationTypeEnum: string
{
case DRIVER_LICENSE = 'driver-license';
case PASSPORT = 'passport';
case NATIONAL_ID = 'national-id';
case RESIDENCE_PERMIT = 'residence-permit';
case PAN_CARD = 'pan-card';
case VOTER_ID = 'voter-id';
public static function toArray(): array
{
return array_map(fn($case) => $case->value, self::cases());
}
public function label(): string
{
return match ($this) {
self::DRIVER_LICENSE => 'Driver License',
self::PASSPORT => 'Passport',
self::NATIONAL_ID => 'National ID',
self::RESIDENCE_PERMIT => 'Residence Permit',
self::PAN_CARD => 'PAN Card',
self::VOTER_ID => 'Voter ID',
};
}
public static function labels(): array
{
return array_reduce(self::cases(), function ($carry, $case) {
$carry[$case->value] = $case->label();
return $carry;
}, []);
}
public static function fromValue(string $value): ?self
{
foreach (self::cases() as $case) {
if ($case->value === $value) {
return $case;
}
}
return null;
}
public static function values(): array
{
return array_combine(
array_map(fn($case) => $case->name, self::cases()),
array_map(fn($case) => $case->value, self::cases())
);
}
}
Usage Examples
Dropdown Options
<select name="verification_type">
@foreach (VerificationTypeEnum::labels() as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
</select>
Safe Parsing from User Input
$type = VerificationTypeEnum::fromValue($request->input('verification_type'));
if (!$type) {
abort(400, 'Invalid verification type.');
}
Form Request Validation
use Illuminate\Validation\Rules\Enum;
public function rules()
{
return [
'verification_type' => ['required', new Enum(VerificationTypeEnum::class)],
];
}
Model Casting
protected $casts = [
'verification_type' => VerificationTypeEnum::class,
];
Bonus: DRY with a BaseEnum Trait (Recommended)
If you have many enums, extract shared logic into a trait:
trait BaseEnum
{
public static function toArray(): array
{
return array_map(fn($case) => $case->value, self::cases());
}
public static function values(): array
{
return array_combine(
array_map(fn($case) => $case->name, self::cases()),
array_map(fn($case) => $case->value, self::cases())
);
}
public static function fromValue(string $value): ?self
{
foreach (self::cases() as $case) {
if ($case->value === $value) return $case;
}
return null;
}
public static function labelFrom(string $value): ?string
{
return self::fromValue($value)?->label() ?? 'Unknown';
}
}
Then reuse:
enum VerificationTypeEnum: string
{
use BaseEnum;
// ...
}
and in model create readable enum column attributes
class ModelName extends Model
{
/**
* use as $item->type for value or $item->type_label for readble label
*/
public function getTypeLabelAttribute(): ?string
{
if (empty($this->type)) return 'Unknown';
if (is_string($this->type)) {
return VerificationTypeEnum::labelFrom((string) $this->type);
}
return $this->type->label();
}
}
and append the value in collection
$items = Verification::where('user_id', $user->id)
->orderBy('id', 'desc')->get()
->each(fn($item) => $item->append('type_label'));
If you want type_label always available when calling toArray() or toJson(), add this to your model then no need to manually append()
again.
protected $appends = ['type_label'];
Conclusion
Enums in Laravel don’t have to be limited to just a list of values. With a few simple additions, you can:
- Build cleaner forms
- Handle user input safely
- Reuse logic consistently
- Improve readability in your models and controllers
Whether you’re building admin panels, APIs, or complex validation logic, enhanced enums make your Laravel codebase more robust and maintainable.