enums

PHP backed string enums used instead of constants or magic strings. Enums include `label()` and `color()` helper methods and are cast on Eloquent models.

SKILL.md

GitHub

Enums

When to Use

  • When a domain field has a closed set of values (status, type, category).
  • When you want type safety, autocomplete, and safer refactors than raw strings.
  • When values are stored in the database and cast on Eloquent models.

When NOT to Use

  • For open-ended or user-defined values that can change at runtime.
  • For free-text labels coming from external systems that are not a stable finite set.

Preconditions

  • PHP version supports enums.
  • Enum classes are placed in app/Enums/.
  • Related Eloquent models cast enum-backed columns.

Rules

  • Use backed string enums — never use plain constants or magic strings for finite sets of values
  • Include label(): string and color(): string helper methods on every enum
  • Use color() for UI color tokens (for example Tailwind tokens like gray, green, red) unless the consuming UI explicitly requires a different format
  • Place all enums in app/Enums/
  • Always cast enum columns in model casts() methods
  • Use enum string values in migrations: $table->string('status')->default('draft')
  • Reference enum cases in code, never raw strings: Status::Draft not 'draft'
  • Use match expressions in label() and color() — never if/else chains
  • Enum naming: PascalCase for enum classes and PascalCase for cases (Status::Draft)

Examples

enum Status: string
{
    case Draft    = 'draft';
    case Active   = 'active';
    case Archived = 'archived';

    public function label(): string
    {
        return match ($this) {
            self::Draft    => 'Draft',
            self::Active   => 'Active',
            self::Archived => 'Archived',
        };
    }

    public function color(): string
    {
        return match ($this) {
            self::Draft    => 'gray',
            self::Active   => 'green',
            self::Archived => 'red',
        };
    }
}
// Model cast
protected function casts(): array
{
    return [
        'status' => Status::class,
    ];
}

// Usage
if ($invoice->status === Status::Draft) { ... }
echo $invoice->status->label(); // 'Draft'

Anti-Patterns

  • Using raw strings instead of enum cases: 'draft' instead of Status::Draft
  • Using integer-backed enums when string enums are more readable
  • Forgetting to cast enum columns in the model's casts() method
  • Using if/else chains instead of match expressions in label() or color()
  • Putting business logic inside enum methods (beyond label/color presentation helpers)
  • Using enums for values that are dynamic, user-generated, or frequently changing

References