← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

match Expression (PHP 8.0)

PHP PHP 8.0+ Intermediate
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list rector, phpcs, and php-cs-fixer — all specialist/configurable tools rather than default linters. These tools can flag switch statements that should be match expressions, or catch misuse of match (e.g. missing default arm), but it requires deliberate tool configuration rather than out-of-the-box catching.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix describes replacing switch statements with match() — a pattern-level substitution within a single block. It's more than a one-liner because you must verify strict vs loose comparison semantics and add a default arm, but it stays within a single component and doesn't span multiple files.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Match expressions apply at the individual statement level in web, cli, and queue-worker contexts, but the choice is scoped to wherever a given switch/match lives. Misuse (e.g. missing default arm causing UnhandledMatchError in production) is localised to that code path and doesn't impose a cross-cutting structural burden on the codebase.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field explicitly identifies this: developers assume match is just cleaner switch syntax, but it uses strict comparison (===) instead of loose (==), and throws UnhandledMatchError for unmatched values instead of silently falling through. These are meaningful behavioural differences that contradict how the superficially similar switch statement works — a competent developer migrating switch to match without this knowledge will introduce subtle bugs.

About DEBT scoring →

Also Known As

PHP match match expression PHP 8 match vs switch

TL;DR

A stricter, expression-based alternative to switch that uses strict comparison, returns a value, and throws on unmatched input.

Explanation

The match expression was introduced in PHP 8.0 as a replacement for switch with three key improvements: it uses strict (===) comparison instead of loose (==), each arm is an expression returning a value (no break needed), and it throws an UnhandledMatchError if no arm matches (unlike switch which silently falls through). Multiple conditions can be comma-separated in a single arm. match is particularly useful for mapping one value to another without mutation.

Common Misconception

match is just switch with cleaner syntax. match uses strict comparison (===) while switch uses loose comparison (==) — this prevents type juggling bugs. match also throws UnhandledMatchError for unmatched values instead of silently falling through, making it safer by default.

Why It Matters

Match expressions use strict comparison, return a value, and throw an UnhandledMatchError for unmatched cases — all three of which switch statements silently get wrong. They eliminate entire classes of bugs that switch creates through type coercion and fall-through.

Common Mistakes

  • Using match when you need fall-through across multiple conditions — match has no fall-through by design.
  • Forgetting match throws UnhandledMatchError for unmatched values — always include a default arm if exhaustiveness is not guaranteed.
  • Using match for complex multi-statement logic per arm — it returns a single expression, use if/else for multi-line branches.
  • Assuming match works like switch for loose comparisons — match is always strict (===).

Code Examples

💡 Note
match() returns a value (assign or return directly), never falls through, and uses strict comparison — three improvements over switch.
✗ Vulnerable
// switch with type coercion — '1' matches 1:
switch ($status) {
    case 1: return 'active'; // '1' also matches — loose comparison
    case 0: return 'inactive';
}

// match uses strict comparison:
return match($status) {
    1 => 'active',
    0 => 'inactive',
    default => throw new UnhandledMatchError(),
};
✓ Fixed
// match is strict (===), exhaustive, and expression-based
$label = match($order->status) {
    'pending'   => 'Awaiting payment',
    'paid'      => 'Processing',
    'shipped'   => 'On the way',
    'cancelled' => 'Cancelled',
    default     => throw new \UnexpectedValueException("Unknown status: {$order->status}"),
};

// No default = UnhandledMatchError on unmatched value — catches missing cases at runtime
// PHPStan/Psalm can also verify exhaustiveness at analysis time

Added 15 Mar 2026
Edited 22 Mar 2026
Views 64
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 4 pings S 5 pings S 2 pings M 2 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 13 Amazonbot 8 Perplexity 7 Ahrefs 4 Google 3 Unknown AI 3 ChatGPT 3 Majestic 2 SEMrush 2 Claude 1 Bing 1 Meta AI 1 PetalBot 1
crawler 46 crawler_json 2 pre-tracking 1
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
Replace switch statements with match() when returning a value — match uses strict comparison and is exhaustive (throws UnhandledMatchError)
📦 Applies To
PHP 8.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
switch statement returning a value from each case — candidate for match expression
Auto-detectable: ✓ Yes rector phpcs php-cs-fixer
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✓ Auto-fixable Fix: Low Context: Function


✓ schema.org compliant