Do you use switch() often? Does long list of switches make you worried that you would introduce some bug in it and wouldn't notice because how complex and unfriendly the syntax is? Are you bothered by it type coercion behavior?
Fear not. You've gotten our savior, match() expression.
What is match expression?
match() is an expression that allows you to compare a specific value against a series of values and then returns value based on which value matches. return value can be produced by executing function/method calls.
Example:
$roleType = 5;
$role = match ($roleType) {
0 => 'Unauthorized',
1 => 'User',
5 => 'Admin',
default => 'Unauthorized',
};
echo $role;
// Admin
Differences with switch()
switch($roleType){
case 0:
$role = 'Unauthorized';
break;
case 1:
$role = 'User';
break;
case 5:
$role = 'Admin';
break;
}
echo $role;
// Admin
But, with match() its fairly easy to do the same (see first example). It also make writing bug harder and we will talk about that later on.
match()
expression uses strict comparison (===
) to compare values. So while with switch, type juggling happens like this:switch ('foo') {
case 0:
$result = 'Oh no!';
break;
case 'foo':
$result = 'This is what I expected';
break;
}
echo $result;
// Oh no!
here, switch() matches 'foo' with 0 because 'foo' == 0 is true.
But match() ensures strict comparison as it does not use any type coercion. No matter what you strict_types value is, match() is always strict.
echo match ('foo') {
0 => 'Oh no!',
'foo' => 'This is what I expected',
};
// This is what I expected
With switch()
$role = 'User';
switch ($role) {
case 'Unauthorized':
// we are skipping break; here
// so, switch() will match both 'Unauthorized' and 'User' for next case
case 'User':
$isAdmin = false;
break;
case 'Admin':
$isAdmin = true;
break;
}
var_dump($isAdmin);
// bool(false)
With match()
$role = 'User';
$isAdmin = match ($role) {
'Unauthorized', 'User' => false,
// We have declared multiple values before '=>'
'Admin' => true,
};
$grade = 'F';
switch($grade){
case 'F':
$message = 'Better luck next time!';
// we've missed break; here
case 'B':
$message = 'Good Boy';
break;
case 'A':
$message = 'Brilliant!';
break;
}
echo $message;
// Good Boy
All the Boys with F grade will now receive message "Good Boy" even if they failed just because we missed a break. If the cases are more than this, debugging will be harder.
match() will help us to avoid this type of bugs as it does not have such use of break.
consider below situation:
$int1 = 10;
$int2 = 5;
$operator = 'DIVIDE';
switch($operator){
case 'ADD':
$result = $int1 + $int2;
break;
case 'SUBTRACT':
$result = $int1 - $int2;
break;
}
Here, we have forgotten to implement case for 'DIVIDE', but as switch() does not complain about it, this bug may not be discovered easily and may exists for long time and cause other bugs in our system.
match() reports match
throws an UnhandledMatchError
if the condition isn’t matched. So any unhandled case can be caught in development period.
$result = match ($x) {
foo() => bar(), // $x will be matched with return value of foo(), after matching it will return the return value for bar()$this->bar() => $this->something(), // $this->bar() isn't called if above foo() matched with $x$this->baz => $this->other, // We can even match with class properties, and return them too// etc.
};
Future Plan
In future, using blocks and arrow functions may be available to use in match(). Currently only expressions are allowed.
Pattern matching would be cool thing too. I hope we will get that in later versions.
Write comment about this article: