Timeline Taxi Out now: my sci-fi novel Timeline Taxi is published!

PHP 8: match or switch?

PHP 8 introduces the new match expression. A powerful feature that will often be the better choice to using switch. So what exactly are the differences?

Let's start by comparing the two. Here's a classic switch example:

switch ($statusCode) {
    case 200:
    case 300:
        $message = null;
        break;
    case 400:
        $message = 'not found';
        break;
    case 500:
        $message = 'server error';
        break;
    default:
        $message = 'unknown status code';
        break;
}

Here's its match equivalent:

$message = match ($statusCode) {
    200, 300 => null,
    400 => 'not found',
    500 => 'server error',
    default => 'unknown status code',
};

First of all, the match expression is significantly shorter:

That's already quite a lot, but there's even more to it!

# No type coercion

match will do strict type checks instead of loose ones. It's like using === instead of ==. People will probably disagree whether that's a good thing or not, but that's a topic on its own.

$statusCode = '200';

$message = match ($statusCode) {
    200 => null,
    default => 'unknown status code',
};

// $message = 'unknown status code'

Noticed a tpyo? You can submit a PR to fix it. If you want to stay up to date about what's happening on this blog, you can subscribe to my mailing list: send an email to brendt@stitcher.io, and I'll add you to the list.

# Unknown values cause errors

If you forget to check for a value, and when there's no default arm specified, PHP will throw an UnhandledMatchError exception. Again more strictness, but it will prevent subtle bugs from going unnoticed.

$statusCode = 400;

$message = match ($statusCode) {
    200 => 'perfect',
};

// UnhandledMatchError

# Only single-line expressions, for now

Just like short closures, you can only write one expression. Expression blocks will probably get added at one point, but it's still not clear when exactly.

# Combining conditions

You already noticed the lack of break? This also means match doesn't allow for fallthrough conditions, like the two combined case lines in the first switch example. On the other hand though, you can combine conditions on the same line, separated by commas.

So you have the same functionality as switch in this regards, but with less writing, and less ways to screw up. Win-win!

$message = match ($statusCode) {
    200, 300, 301, 302 => 'combined expressions',
};

# Complex conditions and performance

During the RFC discussion, some people suggested the following pattern as an argument against adding the match expression:

$message = [
    $this->matchesRegex($line) => 'match A',
    $this->matchesOtherRegex($line) => 'match B',
][$line] ?? 'no match';

There's one big caveat though: this technique will execute all regex functions first, decreasing performance. A good argument for match.

# Throwing exceptions

Finally, because of throw expressions in PHP 8, it's also possible to directly throw from an arm, if you'd like to.

$message = match ($statusCode) {
    200 => null,
    500 => throw new ServerError(),
    default => 'unknown status code',
};

# Pattern matching

Ok, there's one more thing: pattern matching. It's a technique used in other programming languages, to allow complexer matching than simple values. Think of it as regex, but for variables instead of text.

Pattern matching isn't supported right now, because it's quite a complex feature, but Ilija Tovilo, the RFC author did mention it as a possible future feature. Something to look out for!

# So, switch or match?

If I'd need to summarise the match expression in one sentence, I'd say it's the stricter and more modern version of it's little switch brother.

There are some cases — see what I did there? — where switch will offer more flexibility, especially with multiline code blocks. However, the strictness of the match operator is appealing, and the perspective of pattern matching would be a game-changer for PHP.

I admit I never wrote a switch statement in the past years because of its many quirks; quirks that match actually solve. So while it's not perfect yet, there are use cases that I can think of, where match would be a good… match.

What's your opinion?