Выражение match
разветвляет поток исполнения кода в PHP. Но практически тем же занимается и оператор switch
. Разбираемся, чем они отличаются друг от друга и в каких случаях лучше применять именно match
.
Эта статья больше подходит для тех, кто уже немного знает основы PHP. Если вы еще не разобрались с ним, советуем перед прочтением пройти большую профессию по PHP на Хекслете.
Выражение match
разветвляет поток исполнения кода через проверку совпадения значения с заданным условием. Как и оператор switch
, match
принимает на вход выражение, которое сравнивается с множеством альтернатив. Только в отличие от switch
, оно возвращает значение, похожее на тернарный оператор.
Выражение match
появилось в восьмой версии PHP. Оно выполняет практически те же задачи, что и switch
, но имеет ряд преимуществ.
Рассмотрим пример использования выражения match
:
$subject = 'two';
echo match ($subject) {
'one' => 'foo',
'two' => 'bar',
'three' => 'baz',
default => 'default',
}; // => bar
Если заменить в этом примере match
на блок switch
, код будет длиннее:
$subject = 'two';
switch ($subject) {
case 'one':
$result = 'foo';
break;
case 'two':
$result = 'bar';
break;
case 'three':
$result = 'baz';
break;
default:
$result = 'default';
break;
}
echo $result; // => bar
Давайте более подробно поговорим о том, как работает выражение match
.
В отличие от switch
, выражение match
возвращает результат — возвращаемое значение каждой ветви можно сохранить в переменной. Как и в случае с секциями case
в блоках switch
.
$name = match(2) {
1 => 'One',
2 => 'Two',
};
echo $name; // => Two
Для выражения match
можно задать несколько условий, указав их через запятую. Тогда выражение будет похоже на каскад секций case
в блоке switch
.
match($case) {
'one' => 'fizz',
'two', 'three' => 'bazz',
};
Для условий $case === 'two'
или $case === 'three'
будет возвращено значение ’bazz’
.
В отличие от блоков switch
, которые содержат произвольное количество выражений, в каждой ветви match
есть только одно выражение. Поэтому так делать нельзя:
match($name) {
'foo' =>
initFoo();
processFoo();
};
break
Выражение match
выполняет только первую ветвь алгоритма, который соответствует условию. В отличие от оператора switch
, в match
сквозное исполнение не происходит.
А чтобы при использовании switch
не забыть о ключевом слове break
, PHP продолжает исполнять команды следующей секции case
:
switch ('test') {
case 'test':
sendTestAlert();
case 'send':
sendNuclearAlert();
}
Здесь мы пропустили оператор break
. В результате сквозного исполнения кода выполняется и функция sendNuclearAlert()
, хотя этого не должно было произойти.
Для выражения match
не требуется ключевое слово break
. Оно выполняет одну ветвь, возвращает значение и останавливается:
match ('test') {
'test' => sendTestAlert(),
'send' => sendNuclearAlert(),
};
Читайте также: «Комьюнити у PHP сейчас одно из самых активных»: интервью c разработчиком Yii Framework Александром Макаровым
default
Для выражения match
можно задать шаблон default
, аналогично похожей конструкции в блоке switch
.
Ветвь default
совпадает со всеми условиями, которым не нашлось других совпадений.
match ('Qux') {
'foo' => ...,
'bar' => ...,
default => echo 'Unknown: ' . $name,
};
// => Unknown: Qux
Если блок switch
не обнаруживает совпадения, то PHP продолжает выполнять код. Выражение match
носит исчерпывающий характер. Если совпадения не найдены, и нет конструкции default
, выражение выдает исключение \UnhandledMatchError
.
$value = 3;
match($value) {
1 => 'One',
2 => 'Two',
};
Если ввести такое выражение match
, получим ошибку:
Fatal error: Uncaught UnhandledMatchError in ...
UnhandledMatchError
Если проверяемое выражение не совпало ни с одним из условий, выбрасывается исключение \UnhandledMatchError
.
Это подвид \Error
, новый класс исключений в PHP 8. Почитать о структуре базовых исключений PHP, включая новые классы, можно в этой статье.
Добавить эту функциональность в предыдущие версии PHP можно с помощью полифилла:
class UnhandledMatchError extends \Error {}
Одна из особенностей выражения match
заключается в том, что оно не только сравнивает значение, но и учитывает тип выражения.
function read(mixed $key): string {
return match ($key) {
1 => 'Integer 1',
'1' => 'String 1',
true => 'Bool true',
[] => 'Empty array',
[1] => 'Array [1]',
};
}
read(1); // "Integer 1"
read('1'); // "String 1"
read(true); // "Bool true"
Блок switch
использует слабое сравнение (==)
и приводит типы к нужному значению. В выражениях match
все ветви кода, соответствующие условию, подлежат строгому сравнению (===)
. Это защищает разработчиков от ошибок.
В примере выше каждая ветвь проверяется на предмет соответствия значения и типа.
Читайте также: Как работать с базами данных в PHP с помощью модуля PDO
match
позволяет сравнить значение с выражением.
match($foo){
404 => 'Page not found',
Response::REDIRECT => 'Redirect',
$client->getCode() => 'Client Error',
$response->getCode() => 'Response Error',
default => 'Unknown error'
};
Здесь match
ищет совпадение для $foo
в следующем порядке:
$foo === 404
$foo === Response::REDIRECT
$foo === $client->getCode()
$foo === $response->getCode()
default
Проверка кода завершится, как только будет обнаружено совпадение.
match
и switch
match
Код с выражением match
работает только в PHP версии 8.0 и новее. Для более ранних версий можно бэкпортировать класс исключений \UnhandledMatchError
.
Если выполнить код с выражением match
в предыдущих версиях PHP, возникнет ошибка анализа:
Parse error: syntax error, unexpected '=>' (T_DOUBLE_ARROW) in ... on line ...
match
или switch
Итак, выражение match
— это более строгая и современная альтернатива для оператора switch
.
В некоторых случаях switch
более универсален, особенно если нужно использовать многострочные блоки кода. Но у этого оператора много недостатков, которые исправлены в match
. В целом match
выигрывает благодаря точности и более широким возможностям сопоставления с переданным значением.
Станьте профессиональным PHP-разработчиком с нуля за 10 месяцев На Хекслете есть профессия «PHP-разработчик». Пройдите ее, чтобы изучить один из самых известных языков программирования, освоить популярные фреймворки и создать большое портфолио с проектами на GitHub.