PHP's match(true) Pattern Replaces if/elseif Chains
match arrived in PHP 8.0 billed as a better switch, and it is: strict comparison (no 'abc' == 0 surprises), no fall-through, no break statements, and it's an expression - it returns a value. But the pattern that changed my day-to-day code is the one the docs barely whisper about.
The standard form first
$label = match ($order->status) {
'pending', 'processing' => 'In progress',
'paid', 'shipped' => 'Complete',
'refunded' => 'Refunded',
default => 'Unknown',
};
Multiple values per arm, strict ===, and if no arm matches and there's no default, PHP throws UnhandledMatchError instead of silently doing nothing. That exhaustiveness has caught real bugs for me - a new enum case gets added, and the code that forgot to handle it fails loudly at the exact spot instead of misbehaving downstream.
The gem: match(true)
Because match compares the subject against each arm with ===, giving it true as the subject means: the first arm whose expression evaluates to true wins. Suddenly arms can be arbitrary conditions:
$shipping = match (true) {
$total >= 100 => 0.00,
$weight > 20 => 24.90,
$country !== 'US' => 19.90,
default => 6.90,
};
$size = match (true) {
$bytes >= 1_073_741_824 => round($bytes / 1_073_741_824, 1) . ' GB',
$bytes >= 1_048_576 => round($bytes / 1_048_576, 1) . ' MB',
$bytes >= 1024 => round($bytes / 1024) . ' KB',
default => $bytes . ' B',
};
Range checks, tiered pricing, grading scales, HTTP status classification - every elseif ladder whose branches each assign one value collapses into this shape. The wins are real: it's visibly a single decision producing a single value, arms can't accidentally run together, and you can't forget the variable assignment in one branch (the whole thing is the assignment).
Where I draw the line
- Arms are expressions, not statement blocks. The moment a branch needs three statements and a log call, go back to if/elseif - jamming side effects into match arms reads worse than the ladder did.
- Order matters with match(true): first truthy arm wins, so put the most specific conditions first (exactly like elseif).
- It pairs beautifully with enums and with readonly value objects - match on the enum directly, get exhaustiveness checking against every case.
PHP 8.0 is the floor, which in 2026 is nearly everywhere. Alongside date phrase parsing and null-coalescing assignment, match(true) is on my shortlist of features that make modern PHP genuinely pleasant to read.
Full-stack web developer sharing practical tutorials and building tools that ship.
Got something on your mind?
My inbox is open - no forms disappearing into the void here.
- Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
- Hire me for a project Have something custom in mind? Let's talk scope and timelines.
- Product support Bought something here? I'll help you get it running.
I usually reply within 1-2 business days.