match ($value) { ... } сравнивает значение со списком веток строго через === и возвращает результат первой совпавшей ветки. Несколько значений могут делить одну ветку, default ловит всё остальное, а если ничего не совпало, PHP выбрасывает UnhandledMatchError.
Обратите внимание на точку с запятой после закрывающей скобки: match это выражение, как 1 + 2, поэтому вся конструкция это одна инструкция присваивания. Каждая ветка записывается как values => result, ветки разделяются запятыми, и запятая после последней ветки допустима.
Несколько значений в одной ветке
Перечислите значения через запятую. Ветка совпадает, если проверяемое значение идентично (===) любому из них.
Возвращать match прямо из функции, как здесь, самый распространённый способ его использования.
match и switch
Одно и то же сопоставление записано двумя способами, а входное значение показывает главное различие, сравнение. switch использует ==, поэтому строка "1" совпадает с case 1. match использует ===, поэтому не совпадает.
match | switch | |
|---|---|---|
| Сравнение | строгое === | нестрогое == |
| Результат | возвращает значение | инструкция, ничего не возвращает |
| Проваливание | никогда | да, до break |
| Несколько значений | 1, 2 => | подряд case 1: case 2: |
| Нет совпадения | выбрасывает UnhandledMatchError | ничего не делает |
| Тело ветки | одно выражение | любое число инструкций |
Используйте match, когда превращаете одно значение в другое. Оставляйте switch, когда ветке нужно несколько инструкций или когда смысл как раз в проваливании; оба случая есть на странице про switch.
UnhandledMatchError: когда ни одна ветка не совпала
Без ветки default значение, которое ни с чем не совпало, это ошибка, а не молчаливый null. Это полезно: новый код статуса или опечатка громко падают, а не проскакивают незамеченными.
PHP останавливается с сообщением PHP Fatal error: Uncaught UnhandledMatchError: Unhandled match case of type string. В конфигурации для разработки (с выключенным zend.exception_ignore_args) вместо этого называется значение: Unhandled match case 'XL'. Исправьте это, добавив default => 'other', или перехватите ошибку там, где ожидается неизвестное значение:
match(true) для диапазонов и условий
match сравнивает проверяемое значение с каждой веткой, поэтому, если это значение true, каждая ветка может быть условием. Побеждает первое условие, которое вычисляется в точности в true.
Две детали в этом блоке. Начиная с PHP 8 throw это выражение, поэтому оно может быть результатом ветки. А поскольку сравнение строгое, каждое условие должно возвращать настоящее логическое значение: ветка вроде $name => ... никогда не совпадёт с true, даже если $name непустая строка. Вычисляется только совпавшая ветка, поэтому throw срабатывает лишь для отрицательного возраста.
match с перечислениями
match и перечисления хорошо сочетаются: внутри метода enum match ($this) сопоставляет каждый вариант со значением. Про сами перечисления смотрите enum в PHP.
default здесь нет намеренно. Если кто-то позже добавит пятый вариант, вызов color() для него выбросит ошибку, а не вернёт неправильный цвет.
Несколько инструкций в одной ветке
Ветка содержит одно выражение, поэтому 'save' => { ...; ... } это недопустимый PHP. Вынесите работу в функцию и вызовите её из ветки. Функции несовпавших веток никогда не вызываются.
Поменяйте $format на 'json' или 'xml' и запустите снова.
Часто задаваемые вопросы
Чем match отличается от switch в PHP?
match сравнивает строго через ===, возвращает значение, никогда не проваливается в следующую ветку, принимает несколько значений через запятую в одной ветке и выбрасывает UnhandledMatchError, когда ни одна ветка не совпала. switch сравнивает нестрого через ==, это инструкция, которая ничего не возвращает, проваливается без break и молча ничего не делает, если ни один case не совпал.
Что происходит, когда ни одна ветка match не совпала?
PHP выбрасывает UnhandledMatchError. Добавьте ветку default => ... для всех остальных значений или перехватите ошибку через try { ... } catch (\UnhandledMatchError $e) { ... }.
Как использовать match с условиями вроде "больше чем" в PHP?
Сопоставляйте с true: match (true) { $age < 13 => 'child', $age < 18 => 'teen', default => 'adult' }. Каждая ветка это условие, и побеждает первое, которое в точности равно true.
Может ли ветка match выполнить несколько инструкций?
Нет, каждая ветка это одно выражение. Поместите инструкции в функцию или метод и вызовите их из ветки, например 'export' => exportCsv($rows).
В какой версии PHP появился match?
В PHP 8.0. В PHP 7 ту же логику пишут через switch или поиск по массиву вроде $labels[$status] ?? 'Unknown'.