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 UnhandledMatchError se 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