Match expression: switch sem falhas de tipo
1. Introdução à Match Expression no PHP 8.0
A expressão match foi introduzida no PHP 8.0 como uma evolução moderna do tradicional switch. Enquanto switch é uma estrutura de controle que executa blocos de código, match é uma expressão — ou seja, ela sempre retorna um valor. Essa distinção fundamental resolve um dos maiores problemas do switch: a comparação frouxa de tipos e a necessidade manual de break para evitar falhas (fallthrough).
A sintaxe básica é simples e intuitiva:
$resultado = match($valor) {
1 => 'um',
2 => 'dois',
3 => 'três',
default => 'outro'
};
Note que não há break, não há case, e o resultado é atribuído diretamente à variável $resultado.
2. Comparação Direta: match vs switch
O switch utiliza comparação frouxa (==), o que pode levar a comportamentos inesperados. Veja o exemplo clássico:
$valor = "1"; // string
switch ($valor) {
case 1:
echo "Inteiro 1";
break;
case "1":
echo "String 1";
break;
}
// Saída: Inteiro 1 (compara como 1 == "1" → true)
Com match, a comparação é estrita (===):
$valor = "1";
$resultado = match($valor) {
1 => 'Inteiro 1',
"1" => 'String 1',
};
echo $resultado; // Saída: String 1
Isso elimina ambiguidades e torna o código mais previsível, especialmente em APIs que recebem dados de fontes externas (JSON, formulários, etc.).
3. Comportamento Exaustivo e Sem break
No switch, esquecer um break causa fallthrough — a execução continua para o próximo caso, muitas vezes gerando bugs difíceis de rastrear. No match, isso é impossível: apenas um braço é executado e seu valor é retornado imediatamente.
Além disso, match exige exaustividade: todos os valores possíveis devem ser cobertos. Se um valor não for correspondido, um UnhandledMatchError é lançado:
$cor = 'roxo';
$hex = match($cor) {
'vermelho' => '#FF0000',
'verde' => '#00FF00',
'azul' => '#0000FF',
};
// UnhandledMatchError: Unhandled match value of type string
Para evitar isso, use default:
$hex = match($cor) {
'vermelho' => '#FF0000',
'verde' => '#00FF00',
'azul' => '#0000FF',
default => '#000000',
};
4. Expressão vs Declaração: Retorno de Valor
A capacidade de retornar valor é uma das maiores vantagens do match. Enquanto no switch você precisa de variáveis auxiliares e break:
// switch tradicional
$desconto = 0;
switch ($categoria) {
case 'premium':
$desconto = 20;
break;
case 'gold':
$desconto = 15;
break;
default:
$desconto = 5;
}
Com match, tudo fica em uma única expressão:
$desconto = match($categoria) {
'premium' => 20,
'gold' => 15,
default => 5,
};
Isso permite criar funções mais enxutas e evitar efeitos colaterais indesejados.
5. Casos Múltiplos e Condições Complexas
O match permite agrupar múltiplos valores em um mesmo braço usando vírgula:
$nivel = match($pontos) {
1, 2, 3 => 'baixo',
4, 5, 6 => 'médio',
7, 8, 9 => 'alto',
default => 'extremamente alto',
};
Também é possível usar expressões condicionais nos braços:
$idade = 25;
$faixa = match(true) {
$idade < 12 => 'criança',
$idade < 18 => 'adolescente',
$idade < 60 => 'adulto',
default => 'idoso',
};
Note que não é possível usar || ou && diretamente nos braços — para condições complexas, use match(true) com expressões booleanas.
6. Tratamento de Tipos Misto e Union Types
O match brilha quando trabalhamos com union types. Suponha uma função que pode receber diferentes tipos:
function processar(mixed $input): string {
return match(true) {
is_int($input) => "Inteiro: " . ($input * 2),
is_string($input) => "String: " . strtoupper($input),
is_null($input) => "Valor nulo",
default => "Tipo desconhecido",
};
}
echo processar(10); // Inteiro: 20
echo processar("php"); // String: PHP
echo processar(null); // Valor nulo
Com switch, isso exigiria múltiplos if aninhados ou verificações manuais de tipo.
7. Casos de Uso Avançados e Boas Práticas
Substituição de switch aninhados
// Antes: switch aninhado
switch ($user->role) {
case 'admin':
switch ($user->status) {
case 'active': $permission = 'full'; break;
case 'suspended': $permission = 'read'; break;
}
break;
case 'editor':
$permission = 'write';
break;
}
// Depois: match encadeado
$permission = match($user->role) {
'admin' => match($user->status) {
'active' => 'full',
'suspended' => 'read',
},
'editor' => 'write',
default => 'none',
};
Combinação com Enum do PHP 8.1
enum Status: string {
case Ativo = 'ativo';
case Inativo = 'inativo';
case Pendente = 'pendente';
}
function mensagemStatus(Status $status): string {
return match($status) {
Status::Ativo => 'Usuário ativo',
Status::Inativo => 'Usuário inativo',
Status::Pendente => 'Aguardando confirmação',
};
}
Quando evitar match
Em loops muito grandes (milhões de iterações), o match pode ser ligeiramente mais lento que um switch otimizado. Para a grande maioria dos casos, porém, a diferença é irrelevante — priorize legibilidade.
8. Erros Comuns e Armadilhas
Erro 1: Exaustividade ignorada
$valor = 5;
match($valor) {
1 => 'um',
2 => 'dois',
};
// UnhandledMatchError: 5 não foi coberto
Erro 2: Vírgula vs => em casos múltiplos
// ERRADO
match($x) {
1, 2, 3 => 'baixo',
};
// CORRETO
match($x) {
1, 2, 3 => 'baixo',
};
A confusão ocorre quando se tenta usar => entre os valores agrupados.
Erro 3: break ou continue dentro de match
foreach($itens as $item) {
match($item) {
'pular' => continue, // Erro! continue não permitido
default => processar($item),
};
}
Para contornar, use if dentro do braço ou reestruture a lógica.
Conclusão
A expressão match do PHP 8.0 representa uma evolução significativa em relação ao switch. Com comparação estrita, ausência de fallthrough, retorno de valor e exaustividade obrigatória, ela torna o código mais seguro, legível e previsível. Ao migrar projetos legados ou escrever novo código, priorize match sempre que precisar de uma estrutura condicional baseada em valores discretos.
Referências
- PHP Manual: Match Expression — Documentação oficial completa com sintaxe, exemplos e notas de versão
- PHP 8.0: The Match Expression - stitcher.io — Artigo técnico detalhado comparando match e switch com exemplos práticos
- Match Expression in PHP 8 - Laravel News — Tutorial focado em casos de uso reais e migração de switch para match
- PHP 8 Match Expression: Everything You Need to Know - Kinsta — Guia abrangente cobrindo sintaxe, armadilhas e boas práticas
- PHP 8.0: Match Expression vs Switch - Amigoscode — Comparação visual e exemplos de código para iniciantes