Reading — step 1 of 7
Learn
PHP 8.1 added native enums — finite, type-safe sets of values. Combined with match expressions (PHP 8.0), they replace many of PHP's old patterns for finite-state code.
Note: Judge0's PHP version may be older — these features need PHP 8.0+ for match and 8.1+ for enums.
Enum basics
<?php
enum Status {
case Active;
case Archived;
case Pending;
}
$s = Status::Active;
if ($s === Status::Active) {
echo "active";
}
Cases are CONSTANTS — exactly equal under ===. Always type-safe.
Backed enums — with values
For enums that need a stored value (database, API, etc.):
enum Status: string {
case Active = 'active';
case Archived = 'archived';
case Pending = 'pending';
}
$s = Status::Active;
echo $s->value; // 'active'
// Parse from value:
$s = Status::from('active'); // Status::Active
$s = Status::from('unknown'); // ValueError thrown
$s = Status::tryFrom('unknown'); // null returned (failable)
String-backed and int-backed are the two options. The value property exposes the underlying value. from() parses (throws on invalid). tryFrom() returns null on invalid.
Methods on enums
enum Status: string {
case Active = 'active';
case Archived = 'archived';
case Pending = 'pending';
public function label(): string {
return match($this) {
Status::Active => 'Active',
Status::Archived => 'Archived',
Status::Pending => 'Pending — Review Required',
};
}
public function isFinal(): bool {
return $this === Status::Archived;
}
}
echo Status::Pending->label(); // 'Pending — Review Required'
Enums can have methods, constants, implement interfaces. Cannot have constructors or properties (apart from the implicit name and optionally value).
Listing all cases
foreach (Status::cases() as $case) {
echo $case->name . ": " . $case->value . "\n";
}
cases() returns all enum values. Useful for dropdowns, validation, etc.
match expressions
The match expression (PHP 8.0+) is like switch but as an EXPRESSION (returns a value), with strict comparison and exhaustive checks:
$status = 'active';
$label = match($status) {
'active' => 'Active',
'archived', 'deleted' => 'Inactive', // multiple values per arm
default => 'Unknown',
};
Differences from switch:
- Returns a value (use as expression)
- Strict equality (
===) — no'1' == 1surprises - No fall-through; no break needed
- Throws
UnhandledMatchErrorif nothing matches and no default
match with conditions
$n = 42;
$category = match(true) {
$n < 0 => 'negative',
$n === 0 => 'zero',
$n < 10 => 'small',
$n < 100 => 'medium',
default => 'large',
};
The match(true) pattern lets you express ranges and complex conditions. Each arm is evaluated as a boolean.
Combining enums and match
This is the killer pattern:
enum Direction { case North; case South; case East; case West; }
function opposite(Direction $d): Direction {
return match($d) {
Direction::North => Direction::South,
Direction::South => Direction::North,
Direction::East => Direction::West,
Direction::West => Direction::East,
};
}
Compiler verifies exhaustiveness in PHP 8.1+ for backed enums. Add a new case → existing matches still need updating to compile.
Common mistakes
- Adding properties to an enum — not allowed. Use methods that compute from this->value.
- Using switch when match would be better — match has strict equality and is exhaustive. Modern PHP code uses match.
- Forgetting tryFrom for fallible parsing — from() throws; tryFrom() returns null. Pick based on whether the input is trusted.
- Mixing enums with strings/ints elsewhere — backed enums make this safer with from()/value, but you can still slip up.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…