Back to Blog

How to Supercharge Laravel Enums with Cleaner Code

Labeling enum values for dropdowns and forms, Array helpers, Safe value resolution, Enum validation, Model casting

Jul 27, 2025 Updated: Jul 27, 2025

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

<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,
];

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.

Contact

Got A Question For Us?

Feel free to ask anything directly on call or fill the form and we will contact back within few hours.