Skip to content
Carlo Fontanos
Carlo Fontanos

Carlo Fontanos

Software Engineer

I build web applications and share what I learn along the way.

© 2026

PHP's match(true) Pattern Replaces if/elseif Chains

C
Carlo Fontanos
· 2 min read

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.

C
Written by Carlo Fontanos

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.

Your details are only used to reply to you.

Keep reading