Jump to content
Development

PHP Match and Enums.

Match and Enums have become a happy place for me writing modern PHP. For those that don’t know, the match expression was added in PHP 8.0 as an alternative to switch. As per the docs:

The match expression is similar to a switch statement but has some key differences:

  • A match arm compares values strictly (===) instead of loosely as the switch statement does.
  • A match expression returns a value.
  • match arms do not fall-through to later cases the way switch statements do.
  • a match expression must be exhaustive

Enums were added in PHP 8.1 “indented to provide a way to define a closed set of possible values for the type” and they can be plain:

Plain PHP Enum

or backed with integer or string values:

This gives us more options for encapsulating state and, with PHP’s type system improvements, we can pass around enum values rather than integer and string literals and we get some nice hand holding from our tools:

Bonus: Laravel handles casting model properties to enums really nicely.

Playing nicely together

As Match expressions are exhaustive and Enums are a closed set of values, if we don’t handle all the cases like this:

Again our IDE / Static Analysis will shout at us “Match expression does not handle remaining value: DoorState::Locked”. You can fix this by handling the missing case or adding a default arm:

Always another thing to learn

These two features have been in PHP for awhile so using them has become commonplace for me, however there’s always something new to learn in programming. In a recent project with a multi-step upload where each step will call different actions depending on the file type I started using this approach where a related action could be handled by another method on the action class:

This works but we love writing tests for our code right? These actions can be quite complicated and testing individual class methods can require a lot of setup related to other things on that class that a unit test for that specific method isn’t actually testing. For example we don’t want to fake a file or file upload in a unit test that is only testing specific data flows from the bigger upload process. So it was better to refactor to instantiating separate actions in each arm instead like this:

Now we can have simpler unit tests for the separate action classes, nice. But… in some cases I wanted to do more before calling another action. For example, create a DTO from validated file data specific to the action to process and save it, something like:

As PHP doesn’t [yet] support multi-line short closures I didn’t think it was possible to inline this in the match arm. I was wrong as PHP has supported Immediately Invoked Function Execution aka IFFE (Iffy!) since PHP 7, so we can combine this functionality to do this

Whilst the syntax is a little verbose, this feels like a really nice approach to me and great to have another option to reach for.

Wishful thinking folded hands

That being said I do still hope that some day we will be able to do this:

Or even this:

Blurred lines

As much as I love the Match + Enum combination I recently found a case where I preferred not to use it. Here we have a Laravel collection and are filtering it. The filter method will keep the values that return true from the callback:

It is possible to group the conditions that will return false by comma separating them but this felt like a step too far as more conditions and more complicated conditions may have to be added. Therefore I fell back to using a standard guard clause like this:

What do you think? What are your favourite ways to use Enums and Match in PHP? What’s your favourite modern PHP feature?

Looking for help with a PHP Project?

Talk to us today about our Team Augmentation service to see how we can help you with your current PHP Project.

Contact

Laravel Partner

Since 2014, we’ve built, managed and upgraded Laravel applications of all types and scales with clients from across the globe. We are one of Europe’s leading Laravel development agencies and proud to support the framework as an official Laravel Partner.

Get in touch

Vue Experts

We use Vue alongside Laravel on many of our projects. We have grown our team of experts and invested heavily in our knowledge of Vue over the last five years.

Get in touch
Top