An enum can carry methods, static methods, constants and traits, and it can implement interfaces, so the rules about a status live next to its cases instead of in if chains across the codebase. Inside a method, $this is the current case. What an enum cannot have is state: declaring a property is a compile error ("Enum OrderStatus cannot include properties"), and it can neither extend nor be extended.
<?php
interface HasLabel { public function label(): string; }
enum OrderStatus: string implements HasLabel {
case Pending = 'pending'; case Paid = 'paid';
case Shipped = 'shipped'; case Cancelled = 'cancelled';
const DEFAULT = self::Pending; // a constant may alias a case
public function label(): string { return ucfirst($this->value); } // $this is the case
public static function open(): array { return [self::Pending, self::Paid]; }
}
echo OrderStatus::DEFAULT->label(), ' ', count(OrderStatus::open()), "\n";
var_dump(OrderStatus::Shipped instanceof HasLabel);Output
Pending 2 bool(true)
Keep enum methods pure functions of the case: an enum that reads configuration or a database has become a service and belongs in a class (Interfaces and Generators).