(PHP 8)
Выражение match
предназначено для ветвления потока исполнения на
основании проверки совпадения значения с заданным условием.
Аналогично оператору switch
, выражение
match
принимает на вход выражение, которое сравнивается
с множеством альтернатив. Но, в отличие от switch
,
оно обрабатывает значение в стиле, больше похожем на тернарный оператор.
Также, в отличие от switch
, используется строгое сравнение
(===
), а не слабое (==
).
Выражение match доступно начиная с PHP 8.0.0.
Пример #1 Структура выражения match
<?php
$return_value = match (subject_expression) {
single_conditional_expression => return_expression,
conditional_expression1, conditional_expression2 => return_expression,
};
?>
Пример #2 Простой пример использования match
<?php
$food = 'cake';
$return_value = match ($food) {
'apple' => 'На столе лежит яблоко',
'banana' => 'На столе лежит банан',
'cake' => 'На столе стоит торт',
};
var_dump($return_value);
?>
Результат выполнения данного примера:
string(35) "На столе стоит торт"
Замечание: Результат
match
использовать не обязательно.
Замечание: Выражение
match
должно завершаться точкой с запятой;
.
Выражение match
похоже на оператор
switch
за исключением некоторых ключевых отличий:
match
используется строгое сравнение (===
).
match
возвращает результат.
match
исполняется только одна, первая подошедшая, ветвь кода, тогда как
в switch
происходит сквозное исполнение начиная с подошедшего условия и
до первого встретившегося оператора break
.
match
должно быть исчерпывающим.
Также как и оператор switch
, match
последовательно проводит проверки на совпадение с заданными условиями.
Выполнение кода условий происходит лениво, т.е. код следующего условия выполняется только
если все предыдущие проверки провалились. Будет выполнена только одна ветвь кода,
соответствующая подошедшему условию.
Пример:
<?php
$result = match ($x) {
foo() => ...,
$this->bar() => ..., // $this->bar() не будет выполнен, если foo() === $x
$this->baz => beep(), // beep() будет выполнен только если $x === $this->baz
// etc.
};
?>
Условия в match
могут быть множественными. В этом случае их следует разделять запятыми.
Множественные условия работают по принципу логического ИЛИ и, по сути, являются
сокращённой формой для случаев, когда несколько условий должны обрабатываться идентично.
<?php
$result = match ($x) {
// Множественное условие:
$a, $b, $c => 5,
// Аналогично трём одиночным:
$a => 5,
$b => 5,
$c => 5,
};
?>
Также можно использовать шаблон default
.
Этот шаблон совпадает с чем угодно, для чего не нашлось совпадений раньше.
К примеру:
<?php
$expressionResult = match ($condition) {
1, 2 => foo(),
3, 4 => bar(),
default => baz(),
};
?>
Замечание: Использование нескольких шаблонов default приведёт к фатальной ошибке
E_FATAL_ERROR
.
Выражение match
должно быть исчерпывающим. Если
проверяемое выражение не совпало ни с одним из условий, то будет
выброшено исключение UnhandledMatchError.
Пример #3 Пример необработанного выражения
<?php
$condition = 5;
try {
match ($condition) {
1, 2 => foo(),
3, 4 => bar(),
};
} catch (\UnhandledMatchError $e) {
var_dump($e);
}
?>
Результат выполнения данного примера:
object(UnhandledMatchError)#1 (7) { ["message":protected]=> string(33) "Unhandled match value of type int" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) ["file":protected]=> string(9) "/in/ICgGK" ["line":protected]=> int(6) ["trace":"Error":private]=> array(0) { } ["previous":"Error":private]=> NULL }
Выражение match
можно использовать не только для проверки идентичности,
но и для любых выражений, возвращающих логическое значение. В этом случае в качестве входного
параметра передаётся выражение true
.
Пример #4 Использование match для ветвления в зависимости от вхождения в диапазоны целых чисел
<?php
$age = 23;
$result = match (true) {
$age >= 65 => 'пожилой',
$age >= 25 => 'взрослый',
$age >= 18 => 'совершеннолетний',
default => 'ребёнок',
};
var_dump($result);
?>
Результат выполнения данного примера:
string(11) "совершеннолетний"
Пример #5 Использование match для ветвления в зависимости от содержимого строки
<?php
$text = 'Bienvenue chez nous';
$result = match (true) {
str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en',
str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr',
// ...
};
var_dump($result);
?>
Результат выполнения данного примера:
string(2) "fr"