match ($value) { ... } compara um valor com uma lista de braços usando o estrito === e retorna o resultado do primeiro braço que bate. Vários valores podem dividir um braço, default pega o resto, e se nada bater o PHP lança um UnhandledMatchError.
Repare no ponto e vírgula depois da chave de fechamento: match é uma expressão, como 1 + 2, então o conjunto todo é uma instrução de atribuição. Cada braço é valores => resultado, separados por vírgulas, e uma vírgula depois do último braço é permitida.
Vários valores num braço
Liste os valores com vírgulas. O braço bate se o sujeito for idêntico (===) a qualquer um deles.
Retornar o match direto de uma função, como aqui, é o jeito mais comum de usá-lo.
match ou switch
O mesmo mapeamento escrito dos dois jeitos, com uma entrada que mostra a maior diferença: a comparação. O switch usa ==, então a string "1" bate com case 1. O match usa ===, então não bate.
match | switch | |
|---|---|---|
| Comparação | estrita === | frouxa == |
| Resultado | retorna um valor | instrução, não retorna nada |
| Fallthrough | nunca | sim, até um break |
| Vários valores | 1, 2 => | empilhados case 1: case 2: |
| Nada bate | lança UnhandledMatchError | não faz nada |
| Corpo de um ramo | uma expressão | quantas instruções quiser |
Use match quando você está transformando um valor em outro. Mantenha o switch quando um ramo precisa de várias instruções ou quando o fallthrough é o objetivo; a página sobre switch tem os dois casos.
UnhandledMatchError: quando nenhum braço bate
Sem um braço default, um valor que não bate com nada é um erro, não um null silencioso. Isso é uma vantagem: um novo código de status ou um erro de digitação falha de forma visível em vez de passar despercebido.
O PHP para com PHP Fatal error: Uncaught UnhandledMatchError: Unhandled match case of type string. Uma configuração de desenvolvimento (com zend.exception_ignore_args desligado) mostra o valor: Unhandled match case 'XL'. Corrija adicionando default => 'other', ou capturando o erro onde um valor desconhecido é esperado:
match(true) para intervalos e condições
O match compara o sujeito com cada braço, então se o sujeito for true, cada braço pode ser uma condição. A primeira condição que avaliar exatamente como true vence.
Dois detalhes nesse bloco. throw é uma expressão desde o PHP 8, então pode ser o resultado de um braço. E como a comparação é estrita, cada condição precisa retornar um booleano de verdade: um braço como $name => ... nunca bate com true, mesmo quando $name é uma string não vazia. Só o braço que bate é avaliado, então o throw só roda para uma idade negativa.
match com enums
match e enums combinam: dentro de um método de enum, match ($this) mapeia cada caso para um valor. Veja enums no PHP para os enums em si.
Sem default aqui, de propósito. Se alguém adicionar um quinto caso depois, chamar color() nele lança um erro em vez de retornar uma cor errada.
Várias instruções num braço
Um braço contém uma expressão, então 'save' => { ...; ... } não é PHP válido. Mova o trabalho para uma função e chame-a a partir do braço. As funções dos braços que não batem nunca são chamadas.
Mude $format para 'json' ou 'xml' e rode de novo.
Perguntas frequentes
Qual a diferença entre match e switch no PHP?
O match compara com o estrito ===, retorna um valor, nunca cai para o próximo braço, aceita vários valores separados por vírgula por braço e lança um UnhandledMatchError quando nenhum braço bate. O switch compara com o == frouxo, é uma instrução que não retorna nada, cai para o próximo case sem break e não faz nada em silêncio quando nenhum case bate.
O que acontece quando nenhum braço bate numa expressão match?
O PHP lança um UnhandledMatchError. Adicione um braço default => ... para tratar todos os outros valores, ou capture o erro com try { ... } catch (\UnhandledMatchError $e) { ... }.
Como uso match com condições como maior que no PHP?
Use true como sujeito: match (true) { $age < 13 => 'child', $age < 18 => 'teen', default => 'adult' }. Cada braço é uma condição, e a primeira que for exatamente true vence.
Um braço do match pode executar várias instruções?
Não, cada braço é uma única expressão. Coloque as instruções numa função ou num método e chame a partir do braço, por exemplo 'export' => exportCsv($rows).
Qual versão do PHP adicionou o match?
O PHP 8.0. No PHP 7, a mesma lógica precisa de uma instrução switch ou de uma consulta a um array, como $labels[$status] ?? 'Unknown'.