match ($value) { ... } compares a value against a list of arms with strict === and returns the result of the first arm that matches. Several values can share an arm, default catches the rest, and if nothing matches PHP throws an UnhandledMatchError.
Note the semicolon after the closing brace: match is an expression, like 1 + 2, so the whole thing is one assignment statement. Each arm is values => result, separated by commas, and a trailing comma after the last arm is allowed.
Multiple values in one arm
List the values with commas. The arm matches if the subject is identical (===) to any of them.
Returning match directly from a function, as here, is the most common way to use it.
match vs switch
The same mapping written both ways, with one input that shows the biggest difference: comparison. switch uses ==, so the string "1" matches case 1. match uses ===, so it does not.
match | switch | |
|---|---|---|
| Comparison | strict === | loose == |
| Result | returns a value | statement, returns nothing |
| Fallthrough | never | yes, until break |
| Several values | 1, 2 => | stacked case 1: case 2: |
| No match | throws UnhandledMatchError | does nothing |
| Body of a branch | one expression | any number of statements |
Use match when you are turning one value into another. Keep switch when a branch needs several statements or when fallthrough is the point; the switch page has both cases.
UnhandledMatchError: when no arm matches
Without a default arm, a value that matches nothing is an error, not a silent null. That is a feature: a new status code or a typo fails loudly instead of slipping through.
PHP stops with PHP Fatal error: Uncaught UnhandledMatchError: Unhandled match case of type string. A development setup (with zend.exception_ignore_args off) names the value instead: Unhandled match case 'XL'. Fix it either by adding default => 'other', or by catching the error where an unknown value is expected:
match(true) for ranges and conditions
match compares the subject with each arm, so if the subject is true, every arm can be a condition. The first condition that evaluates to exactly true wins.
Two details in that block. throw is an expression since PHP 8, so it can be the result of an arm. And because the comparison is strict, each condition must return a real boolean: an arm like $name => ... never matches true even when $name is a non-empty string. Only the arm that matches is evaluated, so the throw runs only for a negative age.
match with enums
match and enums fit together: inside an enum method, match ($this) maps each case to a value. See PHP enums for enums themselves.
No default here on purpose. If someone adds a fifth case later, calling color() on it throws instead of returning a wrong color.
Several statements in one arm
An arm holds one expression, so 'save' => { ...; ... } is not valid PHP. Move the work into a function and call it from the arm. The functions of the arms that do not match are never called.
Change $format to 'json' or 'xml' and run it again.
Frequently Asked Questions
What is the difference between match and switch in PHP?
match compares with strict ===, returns a value, never falls through to the next arm, accepts several comma separated values per arm, and throws an UnhandledMatchError when no arm matches. switch compares with loose ==, is a statement that returns nothing, falls through without break, and silently does nothing when no case matches.
What happens when no arm matches in a PHP match expression?
PHP throws an UnhandledMatchError. Add a default => ... arm to handle every other value, or catch the error with try { ... } catch (\UnhandledMatchError $e) { ... }.
How do I use match with conditions like greater than in PHP?
Match against true: match (true) { $age < 13 => 'child', $age < 18 => 'teen', default => 'adult' }. Each arm is a condition, and the first one that is exactly true wins.
Can a match arm run several statements in PHP?
No, each arm is a single expression. Put the statements in a function or method and call it from the arm, for example 'export' => exportCsv($rows).
Which PHP version added match?
PHP 8.0. On PHP 7 the same logic needs a switch statement or an array lookup such as $labels[$status] ?? 'Unknown'.