Skip to content

Domain Enums

Domain Enums represent finite sets of values with business meaning. They extend PHP 8.1+ backed enums with additional domain-oriented methods through EnumInterface and EnumTrait.

Why Use Domain Enums

PHP native enums provide type safety but lack common domain operations. EnumInterface adds:

  • Human-readable labels for UI display
  • Comparison methods (equals(), isOneOf())
  • Collection helpers (values(), names(), options())
  • Case-insensitive name lookup (tryFromName())

Creating an Enum

Implement EnumInterface and use EnumTrait:

enum BookStatus: string implements EnumInterface
{
    use EnumTrait;

    case Available = 'available';
    case Borrowed = 'borrowed';

    public function label(): string
    {
        return match ($this) {
            self::Available => 'Available',
            self::Borrowed => 'On Loan',
        };
    }
}

Usage

// Compare values
$status->equals(BookStatus::Available);

// Check against multiple values
$status->isOneOf(BookStatus::Available, BookStatus::Borrowed);

// Get all backed values
BookStatus::values();  // ['available', 'borrowed']

// Get all case names
BookStatus::names();  // ['Available', 'Borrowed']

// Get options for select dropdowns (name => label)
BookStatus::options();  // ['Available' => 'Available', 'Borrowed' => 'On Loan']

// Case-insensitive lookup
BookStatus::tryFromName('available');  // BookStatus::Available

Adding Domain Behavior

Enums can encapsulate business rules through custom methods:

enum BookStatus: string implements EnumInterface
{
    // ...

    public function canBeBorrowed(): bool
    {
        return $this === self::Available;
    }

    public function canBeReturned(): bool
    {
        return $this === self::Borrowed;
    }
}

Persistence

Backed enums serialize to their backing value for database storage:

// Store
$row['status'] = $book->getStatus()->value;  // 'available'

// Restore
$status = BookStatus::from($row['status']);