Pure Enums and Backed Enums

An enum (PHP 8.1) is a type with a closed list of cases. A pure enum's cases are only names; a backed enum gives each an int or string to store in a column, a form or JSON. from() maps a stored value back to its case and throws ValueError for unknown ones; tryFrom() returns null, which suits untrusted input. OrderStatus mirrors the sample orders.status column, ENUM('pending','paid','shipped','cancelled').

A pure enum and a string-backed OrderStatus matching the orders.status columnPHP
<?php
enum Shelf { case Front; case Back; }              // pure: the cases are only names
enum OrderStatus: string {                         // backed: each case carries a string
  case Pending = 'pending';  case Paid = 'paid';
  case Shipped = 'shipped';  case Cancelled = 'cancelled';
}
$s = OrderStatus::from('paid');                    // a stored value becomes a case
var_dump($s === OrderStatus::Paid, $s->name, OrderStatus::tryFrom('refunded'));
echo implode(', ', array_column(OrderStatus::cases(), 'value')), "\n";
try { OrderStatus::from('refunded'); } catch (ValueError $e) { echo $e->getMessage(), "\n"; }
try { $s->value = 'shipped'; } catch (Error $e) { echo $e->getMessage(), "\n"; }
Output
bool(true)
string(4) "Paid"
NULL
pending, paid, shipped, cancelled
"refunded" is not a valid backing value for enum OrderStatus
Cannot modify readonly property OrderStatus::$value

Each case is a singleton, so === compares cases, and no case can be created with new, cloned or changed. Every enum implements UnitEnum, backed ones also BackedEnum. Back an enum only when its values leave the process: json_encode(Shelf::Front) fails with "Non-backed enums have no default serialization".