Estruturas de Controle
Um programa que executa sempre as mesmas instruções na mesma ordem é pouco útil. O que torna o software poderoso é a capacidade de tomar decisões — executar um bloco de código em determinada situação e outro bloco em situação diferente. Isso é feito com estruturas de controle.
Neste artigo vamos estudar as principais estruturas de decisão do PHP: if, else, elseif, switch e o match — introduzido no PHP 8 e que representa uma forma muito mais segura e expressiva de lidar com múltiplas condições.
if, else e elseif
A estrutura if é a mais fundamental de todas. Ela avalia uma condição e executa um bloco de código se essa condição for verdadeira.
<?php
$idade = 20;
// if básico — executa o bloco se a condição for true
if ($idade >= 18) {
echo "Maior de idade.";
}
// if + else — executa um bloco ou outro
if ($idade >= 18) {
echo "Maior de idade.";
} else {
echo "Menor de idade.";
}
// if + elseif + else — múltiplas condições em sequência
// O PHP avalia cada condição de cima para baixo
// e executa apenas o primeiro bloco verdadeiro
$nota = 75;
if ($nota >= 90) {
echo "Conceito A";
} elseif ($nota >= 75) {
echo "Conceito B"; // este será executado
} elseif ($nota >= 60) {
echo "Conceito C";
} else {
echo "Reprovado";
}
Uma regra importante: quando o if tem apenas uma instrução, as chaves são opcionais. Mas omiti-las é uma prática que gera bugs difíceis de encontrar — sempre use chaves, sem exceção.
<?php
$logado = true;
// Sem chaves — funciona, mas é perigoso
if ($logado)
echo "Bem-vindo!";
// Com chaves — sempre preferível
// Se você adicionar uma linha depois, ela será executada independentemente da condição
if ($logado) {
echo "Bem-vindo!";
echo "Seu painel está pronto.";
}
Condições compostas
Na prática, raramente verificamos apenas uma condição. Usamos os operadores lógicos && (E) e || (OU) para combinar condições:
<?php
$idade = 25;
$documento = true;
$pagamento = true;
// && (E) — todas as condições precisam ser verdadeiras
if ($idade >= 18 && $documento && $pagamento) {
echo "Acesso liberado.";
}
// || (OU) — basta uma condição ser verdadeira
$ehAdmin = false;
$ehModerador = true;
if ($ehAdmin || $ehModerador) {
echo "Pode moderar conteúdo.";
}
// Combinando && e || — use parênteses para deixar a precedência clara
// Sem parênteses a leitura fica ambígua e propensa a erros
$planoAtivo = true;
$dentroDoLimite = true;
$ehPremium = false;
// Parênteses explicitam a intenção: (plano ativo E dentro do limite) OU é premium
if (($planoAtivo && $dentroDoLimite) || $ehPremium) {
echo "Requisição permitida.";
}
O operador ternário em condições simples
Para atribuições condicionais simples, o operador ternário é uma alternativa compacta ao if/else:
<?php
$pontos = 450;
// if/else convencional
if ($pontos >= 500) {
$nivel = "Ouro";
} else {
$nivel = "Prata";
}
// Ternário — equivalente, mais conciso para casos simples
$nivel = ($pontos >= 500) ? "Ouro" : "Prata";
echo $nivel; // Prata
// Evite ternários aninhados — tornam o código ilegível
// Ruim:
$categoria = ($pontos >= 1000) ? "Platina" : (($pontos >= 500) ? "Ouro" : "Prata");
// Melhor: use if/elseif para múltiplos casos
if ($pontos >= 1000) {
$categoria = "Platina";
} elseif ($pontos >= 500) {
$categoria = "Ouro";
} else {
$categoria = "Prata";
}
switch
O switch compara uma expressão com múltiplos valores possíveis. É uma alternativa ao if/elseif quando você precisa comparar a mesma variável com vários valores diferentes:
<?php
$diaDaSemana = 3;
switch ($diaDaSemana) {
case 1:
echo "Segunda-feira";
break; // break interrompe o switch — sem ele, a execução "cai" para o próximo case
case 2:
echo "Terça-feira";
break;
case 3:
echo "Quarta-feira"; // este será executado
break;
case 4:
echo "Quinta-feira";
break;
case 5:
echo "Sexta-feira";
break;
case 6:
case 7:
// Múltiplos cases sem break — executa o mesmo bloco para ambos
echo "Final de semana";
break;
default:
// default é executado se nenhum case corresponder
echo "Dia inválido";
break;
}
O switch usa comparação frouxa (==) internamente — mais um motivo para preferi-lo apenas em situações adequadas e migrar para match quando possível.
match — a evolução do switch
Introduzido no PHP 8.0, o match resolve os principais problemas do switch:
- Usa comparação estrita (
===) — sem surpresas de coerção de tipos - Não precisa de
break— cada braço retorna um valor e encerra automaticamente - É uma expressão — pode ser atribuído a uma variável diretamente
- Lança
UnhandledMatchErrorse nenhum braço corresponder — falha explicitamente em vez de silenciosamente
<?php
$status = 2;
// match como expressão — retorna um valor
$descricao = match($status) {
1 => "Pendente",
2 => "Aprovado", // este será retornado
3 => "Reprovado",
4, 5 => "Em análise", // múltiplos valores por braço
default => "Desconhecido", // default é obrigatório se não cobrir todos os casos
};
echo $descricao; // Aprovado
Veja a diferença de comportamento entre switch e match com tipos:
<?php
$valor = "1"; // string "1"
// switch usa == — coerção de tipos
switch ($valor) {
case 1:
echo "switch: encontrou!"; // EXECUTA — "1" == 1 após coerção
break;
}
// match usa === — sem coerção
$resultado = match($valor) {
1 => "match: encontrou inteiro",
"1" => "match: encontrou string", // RETORNA ESTE
default => "match: não encontrou",
};
echo $resultado; // match: encontrou string
match com condições complexas
O match também aceita expressões booleanas, tornando-o uma alternativa elegante ao if/elseif em muitos casos:
<?php
$temperatura = 32;
// match com true como sujeito — avalia expressões booleanas
$clima = match(true) {
$temperatura >= 35 => "Muito quente",
$temperatura >= 28 => "Quente", // este será retornado
$temperatura >= 20 => "Agradável",
$temperatura >= 10 => "Frio",
default => "Muito frio",
};
echo $clima; // Quente
<?php
// Exemplo prático: classificação HTTP de status codes
$httpStatus = 404;
$categoria = match(true) {
$httpStatus >= 500 => "Erro do servidor",
$httpStatus >= 400 => "Erro do cliente", // este será retornado
$httpStatus >= 300 => "Redirecionamento",
$httpStatus >= 200 => "Sucesso",
default => "Informativo",
};
echo $categoria; // Erro do cliente
Sintaxe alternativa para templates
Quando você mistura PHP com HTML em arquivos de template, o PHP oferece uma sintaxe alternativa para estruturas de controle que é muito mais limpa do que abrir e fechar blocos com chaves:
<?php $usuarioLogado = true; $nome = "Ana"; ?>
<!-- Sintaxe alternativa: if: ... endif; -->
<?php if ($usuarioLogado): ?>
<header>
<p>Bem-vinda, <?= $nome ?>!</p>
</header>
<?php else: ?>
<header>
<a href="/login">Fazer login</a>
</header>
<?php endif; ?>
Essa sintaxe com : e endif é padrão em frameworks como Laravel (nos arquivos Blade) e em qualquer template PHP tradicional. Muito mais legível do que:
<?php if ($usuarioLogado) { ?>
<p>Bem-vinda!</p>
<?php } else { ?>
<a href="/login">Login</a>
<?php } ?>
Boas práticas em estruturas de controle
Sempre use chaves, mesmo para blocos de uma linha. Omitir chaves é uma das causas mais comuns de bugs introduzidos durante manutenção de código.
Prefira match ao switch em PHP 8. Comparação estrita, sem break, e falha explícita são vantagens que eliminam toda uma categoria de bugs.
Condições negativas são mais difíceis de ler. Sempre que possível, prefira a afirmativa:
<?php
// Difícil de ler — dupla negação
if (!$usuario->naoEstaAtivo()) { ... }
// Claro e direto
if ($usuario->estaAtivo()) { ... }
Extraia condições complexas para variáveis com nome. Isso transforma lógica em documentação:
<?php
// Difícil de entender à primeira leitura
if ($usuario->idade >= 18 && $usuario->documentoVerificado && $plano->estaAtivo() && !$conta->estaBloqueada()) {
// ...
}
// Com variável nomeada — lê-se como prosa
$podeAcessar = $usuario->idade >= 18
&& $usuario->documentoVerificado
&& $plano->estaAtivo()
&& !$conta->estaBloqueada();
if ($podeAcessar) {
// ...
}
Resumo
| Estrutura | Quando usar |
|---|---|
if / else |
Condição única ou poucas ramificações |
elseif |
Múltiplas condições encadeadas na mesma variável |
switch |
Múltiplos valores — apenas em projetos pré-PHP 8 |
match |
Substituto moderno do switch — sempre prefira em PHP 8+ |
match(true) |
Alternativa elegante ao if/elseif com expressões |
| Sintaxe alternativa | Templates PHP com HTML — use if: / endif; |
Referências e leituras para aprofundar
Estruturas de controle — Manual oficial do PHP https://www.php.net/manual/pt_BR/language.control-structures.php Documentação completa de todas as estruturas de controle, incluindo detalhes de comportamento e exemplos.
match — Manual oficial do PHP https://www.php.net/manual/pt_BR/control-structures.match.php Documentação específica do
match, com comparação detalhada comswitche todos os comportamentos do operador.RFC: Match expression v2 — PHP 8 https://wiki.php.net/rfc/match_expression_v2 A proposta formal que introduziu o
matchno PHP 8. Explica detalhadamente os problemas doswitchque omatchresolve.Replace Conditional with Polymorphism — Martin Fowler https://refactoring.guru/replace-conditional-with-polymorphism Padrão de refatoração que elimina
if/elseextensos substituindo-os por polimorfismo. Relevante já neste módulo para cultivar o pensamento correto.MARTIN, Robert C. Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall, 2008. https://www.oreilly.com/library/view/clean-code-a/9780136083238/ Capítulos 3 e 4 abordam funções pequenas e comentários — diretamente relacionados à legibilidade de estruturas condicionais.
PHP: The Right Way — Boas práticas gerais https://phptherightway.com Guia colaborativo com práticas modernas para toda a série.