Using PHP 8.0 match Expression to Replace Switch Statements
Learn how PHP 8.0's match expression offers a cleaner, safer alternative to switch statements, with a worked example, verification steps, and notes on limitations.
30 Jun 2026, 04:08 UTC

The problem with traditional switch
When you need to map a value to a result in PHP, the switch statement is often the first tool reached for. It works, but it has a few drawbacks that can make code harder to read and maintain:
switchonly executes side‑effects; you cannot directly use its result in an expression.- Each case requires an explicit
breakto avoid accidental fall‑through, which is a common source of bugs. - The comparison used is loose (
==), so values like'0'and0are treated as equal, which can surprise developers expecting strict equality.
These issues become noticeable when the mapping logic is part of a larger expression, such as assigning a value to a variable or returning from a function.
Why the match expression helps
Introduced in PHP 8.0, the match expression addresses the shortcomings of switch while keeping the syntax familiar. Key differences:
matchis an expression: it returns a value that can be used immediately.- Each arm uses strict comparison (
===), eliminating the need forbreakand preventing fall‑through. - The syntax is concise, allowing multiple comma‑separated values per arm and even complex expressions as the subject.
Because the opcode generated for a simple match avoids the jump‑table used by switch, it can be marginally faster for scalar comparisons, though the difference is usually negligible in real‑world applications.
Worked example: mapping HTTP status codes to messages
Consider a function that returns a short message for a given HTTP status code. With switch the code looks like this:
function statusMessageSwitch(int $code): string {
switch ($code) {
case 200:
return 'OK';
case 201:
return 'Created';
case 400:
return 'Bad Request';
case 401:
return 'Unauthorized';
case 403:
return 'Forbidden';
case 404:
return 'Not Found';
default:
return 'Unknown';
}
}
The same logic expressed with match is shorter and directly returns the result:
function statusMessageMatch(int $code): string {
return match ($code) {
200 => 'OK',
201 => 'Created',
400 => 'Bad Request',
401 => 'Unauthorized',
403 => 'Forbidden',
404 => 'Not Found',
default => 'Unknown',
};
}
Notice that there is no break and the function body consists of a single return statement. The match expression evaluates the subject ($code) against each arm using strict comparison, so a string like '200' would not match the integer arm 200.
Verifying the behavior
To confirm that your environment supports match and to inspect the generated opcodes, you can run the following commands in a terminal (no special privileges required):
- Check the PHP version:
php -v
Ensure the output shows PHP 8.0 or newer.
- Execute a tiny script that uses
matchand dump its opcodes with the VLD extension:
php -d vld.active=1 -r "echo match(1){1=>'one';default=>'other';}";
Look for the absence of JMPZ jump‑table opcodes that typically appear in a switch implementation.
- Run a simple performance check (optional):
php -r "
$start = microtime(true);
for ($i = 0; $i < 100000; $i++) {
match ($i % 5) {0=>'zero';1=>'one';2=>'two';3=>'three';4=>'four';default=>'other';}
}
echo 'match: ' . (microtime(true)-$start) . "\n";
$start = microtime(true);
for ($i = 0; $i < 100000; $i++) {
switch ($i % 5) {case 0: $r='zero';break; case 1: $r='one';break; case 2: $r='two';break; case 3: $r='three';break; case 4: $r='four';break; default: $r='other';}
}
echo 'switch: ' . (microtime(true)-$start) . "\n";
"
This script measures the time taken to execute 100 000 iterations of each construct. You should see comparable timings, with match often slightly faster due to reduced opcode overhead.
Trade‑offs and limitations
While match is a valuable addition, there are a few considerations to keep in mind:
- Version requirement: The syntax is only available in PHP 8.0 and later. Deploying code that uses
matchon older servers will produce a fatal compile‑time error. If you need to support PHP 7.x, guard the code with a version check or avoidmatchentirely. - Strict comparison: Because
matchuses===, values that are loosely equal but not identical (e.g.,'0'vs0,falsevs0) will not match. This can be beneficial for catching bugs, but it may require adjusting existing logic that relied on loose comparison. - Expression‑only arms: Each arm must be a single expression; you cannot place multiple statements without using a ternary or calling a function. For complex side‑effects, a traditional
switchmight still be clearer.
To verify that your code behaves as expected after switching to match, run your test suite and pay particular attention to edge cases where type juggling previously occurred.
Actionable closing
If you are maintaining a codebase that runs on PHP 8.0 or newer, consider replacing straightforward switch statements with match where you need to return a value. The change reduces boilerplate, eliminates a common class of fall‑through bugs, and can give a tiny performance win. Start by identifying mappings that are currently expressed as switch with a return in each case, refactor them to match, and run your test suite to confirm that strict comparison does not break any existing assumptions. Over time, you’ll find the code easier to read and less prone to accidental fall‑through.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.