The match Expression
PHP 8's match is a sharper, safer cousin of switch : it returns a value, compares strictly, never falls through, and fails loudly on the unexpected. This lesson shows when to reach for it — and the elegant match(true) trick for ranges.
Learn The match Expression in our free PHP course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ The Basics
match takes a subject and a set of arms written value => result . It returns the result of the first arm whose value matches, and because it's an expression , you can assign or echo that result directly. One arm can list several comma-separated values.
2️⃣ Strict Matching (=== not ==)
The headline safety feature: match compares with strict === , whereas switch uses loose == . So a string "1" will not match an integer 1 arm — exactly the type-juggling surprise that switch lets slip through.
3️⃣ No Fall-Through, No break
In a switch , forgetting break makes execution "fall through" into the next case — a perennial source of bugs. match arms are self-contained: exactly one runs, and there's no break to forget.
4️⃣ match(true) for Ranges
Here's the trick that makes match shine. Use match (true) and make each arm a boolean condition ; the first one that's true wins. A long if/elseif ladder collapses into a clean, readable table — perfect for grades, price bands, and thresholds.
5️⃣ The No-Match Case
If nothing matches and there's no default , match throws an UnhandledMatchError . That's a feature : unexpected values fail loudly during testing instead of slipping by. Add a default arm when you want a catch-all, or omit it when you want every case handled explicitly.
Now you try. Fill the ___ blanks to map an HTTP method to an action.
These scrambled lines should map a status code to a label and print it. Put them in the order that prints Status: Not Found .
Define the subject $code first, then open the match , list the arms (each ending in a comma, including default ), close it with ;'} , and finally echo the result. Because match is an expression, the closing ;'} ends the assignment statement. Output: Status: Not Found .
Predict the output before revealing each answer.
Prints str . match uses strict === , so the string "1" does not match the integer 1 arm — it matches the "1" arm.
Throws an UnhandledMatchError . This is deliberate — unexpected values fail loudly rather than passing silently.
Returns C . The first arm ( $n >= 90 ) is false; the second ( $n >= 70 ) is the first true arm, so it wins.
📋 Quick Reference — match vs switch
Write it yourself, run it on onecompiler.com/php or your own machine, then check against the expected output in the comments.
Practice quiz
What does this print? echo match("1") { 1 => "int", "1" => "str", default => "def" };
- int
- def
- str
- UnhandledMatchError
Answer: str. match compares with strict ===, so the string "1" does not equal the integer 1 arm — it matches the "1" arm and prints str.
Which comparison operator does the match expression use?
- === (strict)
- == (loose)
- <=> (spaceship)
- It depends on the values
Answer: === (strict). match always uses strict === comparison, unlike switch which uses loose ==. This avoids type-juggling surprises.
What happens when no arm matches and there is no default arm?
- Returns null
- Returns false
- Silently does nothing
- Throws UnhandledMatchError
Answer: Throws UnhandledMatchError. An unmatched match with no default throws an UnhandledMatchError — a feature, so unexpected values fail loudly.
With $n = 75, what does match(true) { $n >= 90 => "A", $n >= 70 => "C", default => "F" } return?
- A
- C
- F
- It throws an error
Answer: C. In match(true) the first arm that evaluates to true wins. $n >= 90 is false, $n >= 70 is the first true arm, so it returns C.
Is match a statement or an expression?
- An expression that returns a value
- A statement, like switch
- Neither — it is a loop
- A function call
Answer: An expression that returns a value. match is an expression: it evaluates to a single value you can assign or echo directly.
Do match arms fall through like switch cases, requiring break?
- Yes, you need break in each arm
- Only the default arm falls through
- No — exactly one arm runs and there is no break
- Only if you omit default
Answer: No — exactly one arm runs and there is no break. match has no fall-through. Each arm is self-contained, exactly one runs, and there is no break to forget.
How do you make one match arm handle several subject values?
- Stack them like case labels
- List them comma-separated: 301, 302 => "Redirect"
- Use the || operator
- You cannot — one value per arm
Answer: List them comma-separated: 301, 302 => "Redirect". An arm can list several comma-separated values, e.g. 301, 302 => "Redirect".
Why does switch matching "1" against case 1 succeed where match would not?
- switch sorts its cases first
- switch caches results
- switch only compares strings
- switch uses loose == comparison
Answer: switch uses loose == comparison. switch uses loose ==, so "1" == 1 is true. match uses strict ===, so the string would not hit an integer arm.
Can a single match arm run multiple statements?
- Yes, separate them with semicolons
- No — an arm returns a single expression
- Yes, wrap them in braces
- Only inside the default arm
Answer: No — an arm returns a single expression. match arms return a single expression. For multiple statements, call a function from the arm or use switch/if.
What is the idiomatic use of match(true)?
- To always return the default
- To loop over an array
- To replace if/elseif ladders for ranges and conditions
- To compare two booleans
Answer: To replace if/elseif ladders for ranges and conditions. match(true) makes each arm a boolean condition; the first true arm wins — perfect for grades, price bands, and thresholds.