PHP 8.1 introduced native Enums (enumerations), a long-awaited feature that brings proper enumerated types to PHP. Unlike traditional constants or ad-hoc string/integer values, Enums provide a structured, type-safe way to define a fixed set of possible values, such as statuses, user roles, API response codes, or configuration options.
Decompile Enum expressions in php8 files
The simplest form of an Enum is a pure enum, which acts like a set of named constants:
enum Status { case PENDING; case APPROVED; case REJECTED; }
Type-safe: No risk of typos (unlike strings like "pending"
).
Autocompletion: IDEs recognize all possible values.
Comparable with ===
: No ambiguity (unlike loose comparisons with strings/ints).
Usage Example:
function processOrder(Status $status): void { match ($status) { Status::PENDING => log("Waiting for approval"), Status::APPROVED => finalizeOrder(), Status::REJECTED => cancelOrder(), }; } processOrder(Status::APPROVED); // Only accepts valid Status cases
Enums can also map to scalar values (strings or integers), making them useful for database storage or API responses:
enum HttpStatus: int { case OK = 200; case NOT_FOUND = 404; case SERVER_ERROR = 500; }
Explicit backing type (int
or string
).
Retrieve value with ->value
:
echo HttpStatus::OK->value; // 200
Convert back using from()
/tryFrom()
:
$status = HttpStatus::from(404); // Returns HttpStatus::NOT_FOUND $status = HttpStatus::tryFrom(999); // Returns null (safe for invalid values)
Enums can include methods and implement interfaces, behaving like lightweight classes:
enum UserRole: string { case ADMIN = 'admin'; case EDITOR = 'editor'; case GUEST = 'guest'; public function getPermissions(): array { return match ($this) { self::ADMIN => ['create', 'read', 'update', 'delete'], self::EDITOR => ['read', 'update'], self::GUEST => ['read'], }; } }
Usage:
$role = UserRole::ADMIN; $permissions = $role->getPermissions(); // ['create', 'read', 'update', 'delete']
PHP 8.1’s match
expressions pair perfectly with Enums for exhaustive checks:
function redirectStatus(Status $status): string { return match ($status) { Status::PENDING => "Show loading spinner", Status::APPROVED => "Redirect to success page", Status::REJECTED => "Show error message", }; }
Compiler checks: Ensures all cases are handled (unlike switch
).
No fallthrough risks: Unlike switch
, match
is strict.
enum OrderStatus: string { case PAID = 'paid'; case SHIPPED = 'shipped'; case DELIVERED = 'delivered'; } $dbRecord = ['status' => 'paid']; $status = OrderStatus::from($dbRecord['status']); // Converts to Enum
enum FeatureFlag: string { case NEW_UI = 'new_ui'; case BETA_API = 'beta_api'; } if ($user->hasFlag(FeatureFlag::NEW_UI)) { ... }
enum WorkflowState { case DRAFT; case REVIEW; case PUBLISHED; } $currentState = WorkflowState::REVIEW;
Approach | Pros | Cons |
---|---|---|
Enums | Type-safe, autocompletion, methods | PHP 8.1+ only |
Class Constants | Works in older PHP | No type safety, no methods |
Strings/Ints | Simple | Prone to typos, no validation |
No inheritance: Enums can’t extend other Enums/classes.
No dynamic cases: All cases must be declared upfront.
No properties: Only methods are allowed.
PHP 8.1 Enums provide a robust, modern alternative to loose constants, strings, or integers. They improve:
Code clarity (self-documenting options).
Type safety (no invalid values).
Tooling support (IDE autocompletion, static analysis).
Combined with match
expressions, they’re ideal for state management, configuration, and API/database interactions.
Upgrade Note: If you’re still using arrays or constants for fixed sets of values, Enums are a must-adopt feature in modern PHP.
Email, Chat 24/7, Social links