Enums: Backed, Methods and Interfaces

Enums model a fixed set of named values as real objects. Back them with a scalar, give them methods, even have them implement interfaces.

Since PHP 8.1, an enum replaces the old habit of loose class constants with a proper type. A variable typed as Suit can only ever hold one of the declared cases — the compiler guarantees it.

Pure vs backed

A pure enum has only names. A backed enum ties each case to a scalar (string or int), which is what you store in a database and rebuild with from() / tryFrom().

<?php
enum Status: string {
    case Draft     = 'draft';
    case Published = 'published';
}

$s = Status::from('draft');
echo $s->name;   // Draft
echo $s->value;  // draft
var_dump(Status::tryFrom('nope')); // null, no exception

Enums can hold methods and constants, and can implement interfaces — so they carry behaviour, not just identity.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Model an order's lifecycle (Pending, Processing, Shipped, Delivered, Cancelled) as a backed enum for type-safe status storage.
  • Add a label() method to a Status enum so views can display human-friendly text without a separate lookup array.
  • Implement the Stringable interface on a backed enum so it can be embedded directly in SQL queries.

More examples

Backed enum with string values

Backed enums store a scalar value with each case; from() reconstructs the enum from a stored database string.

Example · php
<?php
enum Status: string {
    case Pending    = 'pending';
    case Processing = 'processing';
    case Shipped    = 'shipped';
    case Cancelled  = 'cancelled';
}

$order  = Status::Pending;
echo $order->value;              // pending

$from_db = Status::from('shipped');
echo $from_db->name;             // Shipped

Enum with methods

Enum methods let you attach behaviour to each case, replacing switch statements scattered around the codebase.

Example · php
<?php
enum Suit: string {
    case Hearts   = 'H';
    case Diamonds = 'D';
    case Clubs    = 'C';
    case Spades   = 'S';

    public function color(): string {
        return match($this) {
            self::Hearts, self::Diamonds => 'red',
            self::Clubs,  self::Spades   => 'black',
        };
    }
    public function label(): string {
        return $this->name . ' (' . $this->value . ')';
    }
}

echo Suit::Hearts->color();  // red
echo Suit::Spades->label();  // Spades (S)

Enum implementing an interface

Enums can implement interfaces, allowing them to be used wherever the interface is type-hinted.

Example · php
<?php
interface HasLabel {
    public function label(): string;
}

enum Priority: int implements HasLabel {
    case Low    = 1;
    case Medium = 2;
    case High   = 3;

    public function label(): string {
        return match($this) {
            self::Low    => 'Low Priority',
            self::Medium => 'Medium Priority',
            self::High   => 'High Priority',
        };
    }
}

$tasks = Priority::cases();
foreach ($tasks as $t) {
    echo "{$t->value}: {$t->label()}\n";
}

Discussion

  • Be the first to comment on this lesson.