← Back to PHP Course | Chapter 4: Control Flow | Lesson 8 of 14

PHP match Expression

match is a tidy cousin of switch that hands you back an answer, like a lookup chart where you find your row and read off the result. It is strict, so it only matches exactly the same value.
Syntax
php
$result = match($value) {
    value1 => result1,
    value2, value3 => result2,
    default => default_result,
};

Basic match Expression

match, added in PHP 8.0, compares a value against a set of arms and *returns* the result of whichever one matches — you assign it directly ($label = match($status) {...}) rather than writing separate echo/assignment statements inside each branch, the way switch requires.

Example: Basic match Expression

php
<?php
// Declare `$status`, set to `2`
$status = 2;
$label = match($status) {
    1 => 'Pending',
    2 => 'Active',
    3 => 'Closed',
};
// Print `$label` to the output
echo $label;
?>

Grouping values with Comma

A single match arm can test for several values at once by listing them comma-separated before the => — 1, 2, 3 => low runs the same result for any of those three values, without needing three separate arms.

Example: Grouping values with Comma

php
<?php
// Declare `$quantity`, set to `2`
$quantity = 2;
$level = match($quantity) {
    1, 2, 3 => 'low',
    4, 5, 6 => 'medium',
};
// Print `$level` to the output
echo $level;
?>

Strict Type Comparison

switch uses loose comparison (==), so 0 == 0 can match unexpectedly.

match always compares with strict semantics (===), so a string 1 will never accidentally match an integer 1 — this closes off a whole category of subtle bugs that switch is prone to.

Example: Strict Type Comparison

php
<?php
// Declare `$value`, set to '0'
$value = '0';
$result = match(true) {
    $value === 0 => 'integer zero',
    $value === '0' => 'string zero',
    default => 'other',
};
// Print `$result` to the output
echo $result;
?>

The default Fallback Case

match requires every possible input to be handled — if a value hits no arm and there's no default, PHP throws an UnhandledMatchError instead of silently doing nothing.

That's a deliberate design choice: rather than a case slipping through unnoticed, a missing branch becomes a hard error you can catch immediately.

Example: The default Fallback Case

php
<?php
// Declare `$code`, set to `99`
$code = 99;
// Try running this block; jump to `catch` if it throws
try {
    // Print `match($code) {` to the output
    echo match($code) {
        1 => 'One',
        2 => 'Two',
    };
// Catch \UnhandledMatchError $e
} catch (\UnhandledMatchError $e) {
    // Print `"No arm matched: " . $e->getMessage()` to the output
    echo "No arm matched: " . $e->getMessage();
}
?>

Complex Conditions in match

Passing true as the value being matched, then writing boolean expressions as the arm conditions, lets match evaluate arbitrary comparisons rather than just fixed values — effectively turning it into a strict, expression-based replacement for an elseif ladder.

Example: Complex Conditions in match

php
<?php
// Declare `$age`, set to `25`
$age = 25;
$category = match(true) {
    $age < 13 => 'child',
    $age < 20 => 'teen',
    default => 'adult',
};
// Print `$category` to the output
echo $category;
?>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Leaving out a default arm for an unlisted value, which throws an UnhandledMatchError.
  2. Expecting match to fall through or run several statements per arm, when each arm is a single expression.
  3. Expecting match to compare loosely like switch, so match (1) { 1 => ... } does not match because it uses ===.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.