Match Expression
Learn the PHP 8 match expression, how it improves on switch with strict comparisons and no fall-through, and how to match multiple values in one arm.
Introduction
The previous lesson covered switch, PHP's classic tool for comparing a value against many possibilities. PHP 8 introduced a modern alternative called match, designed specifically to fix the sharp edges of switch: accidental fall-through, loose comparison, and the need to manually assign a result inside every branch.
In this lesson you will learn match's syntax, how it behaves differently from switch, how to match several values in a single arm, and what happens when nothing matches.
- How the match expression is written and how it returns a value directly.
- Why match uses strict (===) comparison and never falls through.
- How to match multiple values in a single arm using commas.
- What UnhandledMatchError is and when it is thrown.
- How an equivalent switch and match compare side by side.
What is match?
match is an expression, not a statement — meaning it directly produces (and can be assigned or returned as) a value, rather than requiring you to echo or assign inside each branch. It was added in PHP 8.0 as a more predictable, more concise way to compare a single value against several possibilities.
Strict Comparison
match compares using === by default, avoiding surprising type-juggling bugs.
Returns a Value
match is an expression — you can assign its result directly to a variable.
No Fall-Through
Each arm is isolated; there is no break to remember and no accidental fall-through.
Throws on No Match
If nothing matches and there is no default, PHP throws UnhandledMatchError.
Basic Syntax
A match expression takes a subject value, compares it against a list of arms (condition => result), and evaluates to the result of the first matching arm. A default arm can be written as an underscore, _, to catch every other case.
<?php
$statusCode = 404;
$message = match ($statusCode) {
200 => "OK",
301, 302 => "Redirect",
404 => "Not Found",
500 => "Server Error",
default => "Unknown Status",
};
echo $message;Not FoundNotice that each arm ends with a comma, not a break, and the whole expression can be assigned straight to $message.
match vs switch
match and switch solve a similar problem, but they behave quite differently under the hood.
switch (classic)
- Compares using loose == by default
- Falls through to the next case without break
- A statement — you assign or echo manually inside each case
- No error if nothing matches and there is no default
match (PHP 8+)
- Compares using strict === by default
- Never falls through — each arm is independent
- An expression — it returns a value directly
- Throws UnhandledMatchError if nothing matches and there is no default
Because match uses ===, matching the string "1" against the integer 1 will not succeed, unlike switch, which would treat them as equal under loose comparison. This removes a whole category of subtle type-juggling bugs.
Matching Multiple Values
Just like grouped switch cases, a single match arm can handle multiple values by separating them with commas. The arm runs if the subject strictly equals any one of the listed values.
<?php
$day = "Sat";
$type = match ($day) {
"Mon", "Tue", "Wed", "Thu", "Fri" => "Weekday",
"Sat", "Sun" => "Weekend",
};
echo $type;WeekendUnhandled Values
If none of the arms match and there is no default (written as _), PHP throws an UnhandledMatchError instead of silently doing nothing. This is a deliberate safety feature — it surfaces missing cases immediately instead of letting a bug hide.
<?php
$grade = "Z";
try {
$result = match ($grade) {
"A" => "Excellent",
"B" => "Good",
};
} catch (\UnhandledMatchError $e) {
$result = "Error: " . $e->getMessage();
}
echo $result;Error: Unhandled match case 'Z'Unless you are certain every possible value is covered, add a default arm (_) to avoid an uncaught UnhandledMatchError crashing your script.
Side-by-Side Example
Here is the same logic — converting a numeric grade into a letter — written first as a switch statement, then as an equivalent match expression, so you can compare the two styles directly.
<?php
$score = 85;
$letter = "";
switch (true) {
case $score >= 90:
$letter = "A";
break;
case $score >= 80:
$letter = "B";
break;
case $score >= 70:
$letter = "C";
break;
default:
$letter = "F";
break;
}
echo $letter;B<?php
$score = 85;
$letter = match (true) {
$score >= 90 => "A",
$score >= 80 => "B",
$score >= 70 => "C",
default => "F",
};
echo $letter;BBoth produce the same result, but the match version needs no break statements, no pre-declared $letter variable, and reads as a single direct assignment. Using match (true) with boolean arms is a common pattern for range-style comparisons like this one.
Common Mistakes
- Expecting match to use loose comparison like switch — it uses strict === by default.
- Forgetting a default arm and letting an UnhandledMatchError crash the script.
- Adding break inside a match arm — it is unnecessary and a syntax error.
- Using match for side effects (like echoing in every arm) instead of returning a value, which defeats its purpose.
Best Practices
- Prefer match over switch in PHP 8+ code for value comparisons.
- Use match(true) with boolean expressions for range-style comparisons.
- Always include a default arm unless you intentionally want UnhandledMatchError.
- Assign the result of match directly to a variable rather than repeating logic in every arm.
Frequently Asked Questions
Can match replace every switch statement?
In most cases yes, especially for simple value comparisons. switch can still be useful when you need to fall through intentionally or run multiple statements per case without producing a single value.
Does match need a default arm?
Not strictly, but without one, an unmatched value throws UnhandledMatchError. It is good practice to include a default unless you have deliberately covered every case.
Which PHP version added match?
match was introduced in PHP 8.0.
Can a match arm run multiple statements?
A match arm evaluates a single expression. For multiple statements, call a function from the arm, or use switch instead.
Key Takeaways
- match is a PHP 8 expression that returns a value directly.
- It compares using strict === by default, unlike switch's loose ==.
- There is no fall-through and no break needed between arms.
- Multiple values can share one arm using a comma-separated list.
- An unmatched value with no default throws UnhandledMatchError.
Summary
The match expression is PHP 8's modern, safer alternative to switch. It compares strictly, never falls through, and returns a value directly, making your code shorter and less error-prone for value-comparison logic.
- You understand how match differs from switch.
- You can match multiple values in a single arm.
- You know what UnhandledMatchError means and how to guard against it.
- You are ready to move on to loops.