PHP: Match expression
The match expression appeared in PHP 8 and solves the same task as switch: it picks a result based on a variable's value. The constructs are similar, but match is shorter and works as an expression. Let's compare them on one example. Here is how you select a text by an order status with switch:
<?php
switch ($status) {
case 'processing':
$statusText = 'Order is being processed';
break;
case 'paid':
$statusText = 'Order is paid';
break;
case 'new':
$statusText = 'New order';
break;
default:
$statusText = 'Unknown status';
}The same thing with match takes less space, and the result goes straight into the variable:
<?php
$statusText = match ($status) {
'processing' => 'Order is being processed',
'paid' => 'Order is paid',
'new' => 'New order',
default => 'Unknown status',
};match (value) {
│
├── 'a' → result 1
├── 'b' → result 2
├── 'c' → result 3
└── default → default result
}To the left of the => arrow is the value to compare, and to the right is any expression that becomes the result. The default arm fires when no value matches and plays the role of else. If several values lead to the same result, they are listed separated by commas:
<?php
$type = match ($size) {
'xs', 's' => 'small',
'm' => 'medium',
'l', 'xl' => 'large',
};The main difference from switch is that match is an expression. The whole construct evaluates to a value, so the result can be assigned to a variable or returned from a function right away. switch cannot do this; it needs a separate variable or a return inside a case. There are other differences too:
matchcompares values strictly, like the===operator, with no automatic type conversion.switchcompares loosely, with==.matchexecutes exactly one arm, so nobreakis needed. Inswitch, withoutbreak, control falls through to the nextcase.- If nothing matches in
matchand there is nodefault, the program terminates with anUnhandledMatchError. In the same case,switchdoes nothing.
Since match returns a value, its result is often returned straight from the function with return:
<?php
function countItems(int $count): ?string
{
return match ($count) {
1 => 'one',
2 => 'two',
default => null,
};
}
print_r(countItems(2)); // => twoTechnically you can always do without match, just as without switch. But when you need to pick a result by specific values of a variable, match expresses that intent most clearly, and such code is easier to read than a chain of elseif.
Instructions
Implement a function calculateDeliveryCost() that takes a delivery country and a parcel weight in kilograms. The function should return the delivery cost.
Each country has two rates: one for parcels weighing up to and including 1 kg, and another for heavier parcels:
'canada': 600 for parcels up to 1 kg, 900 for the rest'usa': 800 for parcels up to 1 kg, 1200 for the rest'germany': 700 for parcels up to 1 kg, 1000 for the rest
If the country is unknown, the function should return null.
Function call examples:
<?php
calculateDeliveryCost('canada', 0.5); // 600
calculateDeliveryCost('canada', 2); // 900
calculateDeliveryCost('usa', 1); // 800
calculateDeliveryCost('france', 1); // nullHint: any expression can appear to the right of the => arrow, including the ternary operator.
Tips
If you've reached a deadlock it's time to ask your question in the «Discussions». How ask a question correctly:
- Be sure to attach the test output, without it it's almost impossible to figure out what went wrong, even if you show your code. It's complicated for developers to execute code in their heads, but having a mistake before their eyes most probably will be helpful.
PHP: Match expression
The match expression appeared in PHP 8 and solves the same task as switch: it picks a result based on a variable's value. The constructs are similar, but match is shorter and works as an expression. Let's compare them on one example. Here is how you select a text by an order status with switch:
<?php
switch ($status) {
case 'processing':
$statusText = 'Order is being processed';
break;
case 'paid':
$statusText = 'Order is paid';
break;
case 'new':
$statusText = 'New order';
break;
default:
$statusText = 'Unknown status';
}The same thing with match takes less space, and the result goes straight into the variable:
<?php
$statusText = match ($status) {
'processing' => 'Order is being processed',
'paid' => 'Order is paid',
'new' => 'New order',
default => 'Unknown status',
};match (value) {
│
├── 'a' → result 1
├── 'b' → result 2
├── 'c' → result 3
└── default → default result
}To the left of the => arrow is the value to compare, and to the right is any expression that becomes the result. The default arm fires when no value matches and plays the role of else. If several values lead to the same result, they are listed separated by commas:
<?php
$type = match ($size) {
'xs', 's' => 'small',
'm' => 'medium',
'l', 'xl' => 'large',
};The main difference from switch is that match is an expression. The whole construct evaluates to a value, so the result can be assigned to a variable or returned from a function right away. switch cannot do this; it needs a separate variable or a return inside a case. There are other differences too:
matchcompares values strictly, like the===operator, with no automatic type conversion.switchcompares loosely, with==.matchexecutes exactly one arm, so nobreakis needed. Inswitch, withoutbreak, control falls through to the nextcase.- If nothing matches in
matchand there is nodefault, the program terminates with anUnhandledMatchError. In the same case,switchdoes nothing.
Since match returns a value, its result is often returned straight from the function with return:
<?php
function countItems(int $count): ?string
{
return match ($count) {
1 => 'one',
2 => 'two',
default => null,
};
}
print_r(countItems(2)); // => twoTechnically you can always do without match, just as without switch. But when you need to pick a result by specific values of a variable, match expresses that intent most clearly, and such code is easier to read than a chain of elseif.
Instructions
Implement a function calculateDeliveryCost() that takes a delivery country and a parcel weight in kilograms. The function should return the delivery cost.
Each country has two rates: one for parcels weighing up to and including 1 kg, and another for heavier parcels:
'canada': 600 for parcels up to 1 kg, 900 for the rest'usa': 800 for parcels up to 1 kg, 1200 for the rest'germany': 700 for parcels up to 1 kg, 1000 for the rest
If the country is unknown, the function should return null.
Function call examples:
<?php
calculateDeliveryCost('canada', 0.5); // 600
calculateDeliveryCost('canada', 2); // 900
calculateDeliveryCost('usa', 1); // 800
calculateDeliveryCost('france', 1); // nullHint: any expression can appear to the right of the => arrow, including the ternary operator.
Tips
If you've reached a deadlock it's time to ask your question in the «Discussions». How ask a question correctly:
- Be sure to attach the test output, without it it's almost impossible to figure out what went wrong, even if you show your code. It's complicated for developers to execute code in their heads, but having a mistake before their eyes most probably will be helpful.
Your exercise will be checked with these tests:
<?php
namespace HexletBasics\Conditionals\MatchExpression;
use HexletBasics\Exercise\TestCase;
class SolutionTest extends TestCase
{
public function test()
{
$this->assertEquals(600, calculateDeliveryCost('canada', 0.5));
$this->assertEquals(600, calculateDeliveryCost('canada', 1));
$this->assertEquals(900, calculateDeliveryCost('canada', 2));
$this->assertEquals(800, calculateDeliveryCost('usa', 1));
$this->assertEquals(1200, calculateDeliveryCost('usa', 3));
$this->assertEquals(700, calculateDeliveryCost('germany', 0.3));
$this->assertEquals(1000, calculateDeliveryCost('germany', 1.5));
$this->assertNull(calculateDeliveryCost('france', 1));
}
}Teacher's solution will be available in:
20:00
