В PHP 8 появилось новое выражение match . Это мощная фича, которая часто будет более удачным выбором, чем использование switch . Так в чем же именно разница?

Давайте начнем со сравнения. Вот классический пример с switch :

switch ($statusCode) {
    case 200:
    case 300:
        $message = null;
        break;
    case 400:
        $message = 'not found';
        break;
    case 500:
        $message = 'server error';
        break;
    default:
        $message = 'unknown status code';
        break;
}

А вот его эквивалент с match :

$message = match ($statusCode) {
    200, 300 => null,
    400 => 'not found',
    500 => 'server error',
    default => 'unknown status code',
};

Прежде всего, выражение match  значительно короче:

  • оно не требует оператора break 
  • оно позволяет объединять различные ветви в одну через запятую
  • оно возвращает значение, поэтому присваивание нужно делать только один раз

Это уже немало, но есть и другие преимущества!

Без приведения типов

match  выполняет строгое сравнение типов вместо нестрогого. Это аналогично использованию ===  вместо == . Возможно, мнения о том, хорошо это или плохо, разойдутся, но это отдельная тема для разговора.

$statusCode = '200';

$message = match ($statusCode) {
    200 => null,
    default => 'unknown status code',
};

// $message = 'unknown status code'


Неизвестные значения вызывают ошибки

Если вы забыли обработать какое-то значение и при этом не указали ветку default , PHP выбросит исключение UnhandledMatchError . Опять же, больше строгости, но это предотвратит появление незамеченных багов.

$statusCode = 400;

$message = match ($statusCode) {
    200 => 'perfect',
};

// UnhandledMatchError

Пока только однострочные выражения

Как и в случае с короткими замыканиями, вы можете написать только одно выражение. Блоки выражений, вероятно, будут добавлены в будущем, но пока неясно, когда именно.

Объединение условий

Вы уже заметили отсутствие break ? Это также означает, что match  не поддерживает сквозное выполнение (fallthrough), как две объединенные строки case  в первом примере с switch . С другой стороны, вы можете объединять условия в одной строке, разделяя их запятыми.

Таким образом, вы получаете ту же функциональность, что и у switch, но с меньшим количеством кода и меньшей вероятностью ошибиться. Сплошные плюсы!

$message = match ($statusCode) {
    200, 300, 301, 302 => 'combined expressions',
};

Сложные условия и производительность

Во время обсуждения RFC некоторые разработчики предлагали следующий паттерн в качестве аргумента против добавления выражения match :

$message = [
    $this->matchesRegex($line) => 'match A',
    $this->matchesOtherRegex($line) => 'match B',
][$line] ?? 'no match';

Однако здесь есть один важный нюанс: при таком подходе сначала будут выполнены все функции регулярных выражений, что снизит производительность. Отличный аргумент в пользу match .

Выбрасывание исключений

Наконец, благодаря выражениям throw в PHP 8, при желании вы можете выбрасывать исключения прямо из ветви выражения.

$message = match ($statusCode) {
    200 => null,
    500 => throw new ServerError(),
    default => 'unknown status code',
};

Сопоставление с шаблоном (Pattern matching)

И еще кое-что: сопоставление с шаблоном. Это техника, используемая в других языках программирования, которая позволяет выполнять более сложное сопоставление, чем просто сравнение со значениями. Представьте себе это как регулярные выражения, но для переменных, а не для текста.

На данный момент сопоставление с шаблоном не поддерживается, так как это довольно сложная фича, но Илиja Товило, автор RFC, упомянул ее как возможную будущую возможность. Будем ждать!

 Посмотрите мое последнее видео: DX matters

Итак, switch или match?

Если бы мне нужно было описать выражение match  одним предложением, я бы сказал, что это более строгая и современная версия его младшего брата switch .

Есть случаи, когда switch  предлагает больше гибкости, особенно с многострочными блоками кода. Тем не менее, строгость оператора match  подкупает, а перспектива появления сопоставления с шаблоном может кардинально изменить PHP.

Признаюсь, за последние годы я практически не писал конструкций switch  из-за их многочисленных причуд — причуд, которые match  успешно решает. И хотя он еще не идеален, я могу представить множество юзкейсов, где match  будет отличным выбором.

А каково ваше мнение?