• Overview
    Key features
    • Observability
    • Auto-scaling
    • Multiframework
    • Security
    Frameworks
    • Django
    • Next.js
    • Drupal
    • WordPress
    • Symfony
    • Magento
    • See all frameworks
    Languages
    • PHP
    • Python
    • Node.js
    • Ruby
    • Java
    • Go
  • Industries
    • Consumer Goods
    • Media/Entertainment
    • Higher Education
    • Government
    • Ecommerce
  • Pricing
  • Featured articles
    • Switching to Platform.sh can help IT/DevOps organizations drive 219% ROI
    • Organizations, the ultimate way to manage your users and projects
  • Support
  • Docs
  • Login
  • Request a demo
  • Free Trial
Meet Upsun. The new, self-service, fully managed PaaS, powered by Platform.sh.Try it now
Blog
Cover image

PHP 8.0 feature focus: match() expressions

php
24 September, 2020
Larry Garfield
Larry Garfield
Director of Developer Experience

In our last episode, we discussed coming improvements to PHP's type system. Today we look at a new construct that makes branching logic more powerful.

PHP has had a switch statement since the dawn of time, modeled on the same construct in C. You've surely seen it before:

<?php
switch ($var) {
    case 'a':
        $message = "The variable was a.";
        break;
    case 'b':
        $message = "The variable was c.";
        break;
    case 'c':
        $message = "The variable was c.";
        break;
    default:
        $message = "The variable was something else.";
        break;
}

print $message;

While it gets the job done, the classic switch has a number of limitations. Most newer languages like Go or Rust have opted for more robust, less error-prone structures that go by a variety of names. And now, PHP has one, too.

Enter match. Unlike switch, match is an expression. That means it evaluates to a value, like so:

<?php
$message = match($var) {
    'a' => 'The variable was a',
    'b' => 'The variable was b',
    'c' => 'The variable was c',
    default => 'The variable was something else',
};

print $message;

There are several things to point out here:

  1. With switch, each case is compared with loose equality ==. With match, each branch is compared with strict equality, ===. That means the types must match, too.
  2. Each branch of the match is a single expression only. No multi-line statements, just a single expression that gets evaluated. If you need complex logic, make it a function or method that you call.
  3. There is no fall through from one branch to the next, so there's no need for a break.
  4. match returns a value. That's its whole reason to exist.
  5. Because it's an expression, a closing ; is needed at the very end, just like with closure definitions.
  6. match is exhaustive. If $var is not === any of the provided values and there is no default, an error will be thrown.

match branches can also be compound and comma-delimited for "OR" like behavior, like so:

<?php
echo match($operator) {
    '+', '-', '*', '/' => 'Basic arithmetic',
    '%' => 'Modulus',
    '!' => 'Negation',
};

match was pitched as a modernized, more useful switch, but I am not sure that's accurate. Rather, I think of match as a more powerful ternary.

In the past, I've often found myself in binary cases where a variable can be assigned to one of two values depending on some condition. The easiest way to write that, I've found, is like this:

<?php
$display = $user->isAdmin()
    ? $user->name() . ' (admin)'
    : $user->name() . ' (muggle)'
;

That's completely valid code and quite useful. If the logic in the condition or in either of the branches is too complex to be easily readable, that's a hint the logic should be refactored out to its own function or method. I've found that to be a really good heuristic for situations like this, as well as leading to very readable, compact, and testable code.

That only works for true/false, however. match, in contrast, works for any number of options but has the same incentives to nudge you toward well-factored, clean code.

If you need more complex conditions than simple identity, you can use match on true:

<?php
$count = get_count();
$size = match(true) {
    $count > 0 && $count <=10 => 'small',
    $count <=50 => 'medium',
    $count >50 => 'huge',
};

Note that since there is no default, a non-match (in this case if $count is 0 or negative) will result in a thrown error rather than silently assigning to null and moving on. That's good, because errors can't propagate to pollute later code.

The match expression RFC comes to us courtesy of Ilija Tovilo.

Tune in next week as we look at another new feature in PHP 8.0 that finally completes work that began in 7.4: Weak Maps.

You can try out pre-release copies of PHP 8.0 today on Platform.sh, with just a one-line change. Give it a whirl, and let us know what your favorite features are.

Get the latest Platform.sh news and resources
Subscribe

Related Content

A festive treat: PHP 8.3 is already available on Platform.sh

A festive treat: PHP 8.3 is already available on Platform.sh

Company
AboutSecurity and complianceTrust CenterCareersPressContact us
Thank you for subscribing!
  •  
Field required
Leader Winter 2023
System StatusPrivacyTerms of ServiceImpressumWCAG ComplianceAcceptable Use PolicyManage your cookie preferencesReport a security issue
© 2024 Platform.sh. All rights reserved.
Supported by Horizon 2020's SME Instrument - European Commission 🇪🇺