What's the Difference Between match and switch in PHP?

match expressions were introduced in PHP 8 while switch statement have existed since PHP 4. They both differ in terms of the following:

Syntactical Differences

A switch statement has the following syntax:

switch (subject) {
    case expr:
        // execute block of statements
        break; // or continue or return
    default:
        // execute block of statements
        break; // or continue or return
}

In switch, the continue statement acts similar to break. It can be useful if, for example, you have a switch inside a loop and wish to continue to the next iteration of the outer loop (in which case, you would use continue 2 for example).

A match expression has the following syntax:

$result = match (subject) {
    expr1, expr2 => value,
    default => value,
};

Essentially, match and switch have the following syntactical differences:

  • match is an expression, while switch is a statement;
  • match must be terminated by a semi-colon (;), however, same is not required for switch;
  • A match arm can have multiple expressions (separated by a comma); they're evaluated in the same way as a logical OR. However, a switch case may only have a single expression;
  • In match, you can only have single-line expressions that return a value when a match arm matches. In switch, however, each case can have multiple statements (i.e. a block of statements) that are executed if the case matches.

Return Value

The match expression evaluates to a value which can be stored in a variable or returned. For example:

// PHP 8+
$subject = 'two';

$result = match ($subject) {
    'one' => 'foo',
    'two' => 'bar',
    'three' => 'baz',
    default => 'default',
};

echo $result; // 'bar'
// PHP 8+
$subject = 'two';

echo match ($subject) {
    'one' => 'foo',
    'two' => 'bar',
    'three' => 'baz',
    default => 'default',
}; // 'bar'

The switch statement on the other hand, does not evaluate to a value itself, but rather executes a different piece of code depending on the case it matches. For example:

// PHP 4+
$subject = 'two';

switch ($subject) {
    case 'one':
        $result = 'foo';
        break;
    case 'two':
        $result = 'bar';
        break;
    case 'three':
        $result = 'baz';
        break;
    default:
        $result = 'default';
        break;
}

echo $result; // 'bar'

You may use return inside a case block to return a value if the switch is used inside a function. For example:

function getValue(string $subject) {
    switch ($subject) {
        case 'one':
            return 'foo';
        case 'two':
            return 'bar';
        default:
            return 'baz';
    }
}

echo getValue('one'); // 'foo'
echo getValue('two'); // 'bar'
echo getValue('non-existent'); // 'baz'

Comparison Strictness

In a switch statement, comparisons are made based on loose/weak equality (==). For example:

switch (8.0) {
  case '8.0':
    $result = 'not expected';
    break;
  case 8.0:
    $result = 'expected';
    break;
}

echo $result; // 'not expected'

In a match expression, comparisons are made based on strict equality (===). For example:

echo match (8.0) {
  '8.0' => 'not expected',
  8.0 => 'expected',
}; // 'expected'

Handling of No Match

When there's no match found, and a default does not exist, the match expression throws an UnhandledMatchError. For example:

// PHP 8+
$subject = 'no-match';

$result = match ($subject) {
    'one' => 'foo',
    'two' => 'bar',
};

// Fatal error: Uncaught UnhandledMatchError

A switch on the other hand, does nothing when there's no matching case and a default is not present. For example:

// PHP 4+
$subject = 'no-match';

switch ($subject) {
    case 'one':
        echo 'foo';
        break;
    case 'two':
        echo 'bar';
        break;
}

Fall-Through

switch continues to execute the statements until the end of the switch block (i.e. they fall-through) till a terminating statement (such as break, continue or return) is found. For example:

// PHP 4+
$subject = 'two';

switch ($subject) {
    case 'one':
        echo 'one;';
    case 'two':
        echo 'two;';
    case 'three':
        echo 'three;';
    default:
        echo 'default;';
}

// output: 'two;three;default;'

In the following example, after the match is found at case 'two', the execution falls-through till case 'three' and stops (as it has a break statement):

// PHP 4+
$subject = 'two';

switch ($subject) {
    case 'one':
        echo 'one;';
    case 'two':
        echo 'two;';
    case 'three':
        echo 'three;';
        break;
    default:
        echo 'default;';
}

// output: 'two;three;'

This is not the case with match arms, however, as they do not fall-through like that. In a match expression, if there's a match, the remaining conditions are not evaluated. For example:

// PHP 8+
$subject = 'two';

$result = match ($subject) {
    'one' => 'one;',
    'two' => 'two;',
    'three' => 'three;',
    default => 'default;',
};

echo $result; // 'two;'

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.