Como Resolver o Erro "Headers Already Sent" no PHP (Solução Definitiva)

Como Resolver o Erro "Headers Already Sent" no PHP (Solução Definitiva)

Você escreve o script de login perfeito. Testa a conexão com o banco, valida a senha e, na hora de redirecionar o usuário para o painel com a função header(), a tela cospe o temido aviso: Warning: Cannot modify header information.

É o clássico batismo de fogo de quem trabalha com PHP. Aquele cliente que estava esperando o sistema rodar liso depara com uma tela cheia de caminhos de arquivos. A boa notícia é que a solução é mais simples do que parece, exigindo apenas que você entenda como o servidor empacota as informações.

O que causa esse bloqueio?

O protocolo HTTP funciona como uma encomenda enviada pelos Correios. Os headers (cabeçalhos HTTP) são a etiqueta colada do lado de fora da caixa, contendo as instruções de entrega e redirecionamento. O conteúdo (seu HTML, um echo, ou até um espaço em branco invisível) é o produto que vai lá dentro.

O PHP precisa enviar a etiqueta (headers) antes de enviar o conteúdo. Se você der um echo, ou deixar uma linha em branco fora da tag <?php, o PHP entende que a caixa já pode ser despachada. Tentar usar header("Location: ...") depois disso é tentar alterar o endereço de uma caixa que já está no caminhão de entrega. O servidor barra na hora.

Como resolver no código: O certo e o errado

O erro acontece quase sempre porque algum texto vazou para a tela antes do comando de redirecionamento. Veja o cenário clássico de erro:


<!-- ERRO COMUM: Um espaço em branco ou HTML antes da tag do PHP -->
 
<?php
$usuario = "admin";
if ($usuario == "admin") {
    // Isso vai falhar porque aquela linha vazia lá em cima já enviou o corpo da página!
    header("Location: painel.php");
    exit;
}
?>

Para corrigir, garanta que absolutamente nada seja impresso antes da função header(). A tag <?php deve ser a primeira coisa no topo do seu arquivo, na linha 1, coluna 1.

Caso o seu sistema tenha uma arquitetura complexa e você realmente precise processar conteúdo antes de redirecionar, a salvação é o controle de buffer de saída com ob_start():


<?php
// Inicia o buffer. Tudo o que for impresso fica retido na memória do servidor.
ob_start(); 

echo "Bem-vindo ao sistema. Carregando...";

// Processamento do banco de dados aqui...

if ($login_correto) {
    // Agora o header funciona, pois o "echo" acima ainda não foi despachado para o navegador!
    header("Location: dashboard.php");
    exit;
}

// Libera o conteúdo da memória para a tela se não houver redirecionamento
ob_end_flush(); 
?>

Aviso: Sempre coloque um exit; ou die(); imediatamente após um header("Location: ..."). Isso impede que o resto da página continue sendo processado ocultamente, economizando recursos e evitando falhas de segurança.

Apostila PHP Progressivo

Domine o PHP Offline e Sem Propagandas 🚀

Se você quer dominar a manipulação de sessões, redirecionamentos, arquitetura de código e ter todo o material à mão sem depender da internet, o conteúdo completo está na nossa Apostila PHP Progressivo em PDF. O atalho para não travar mais nesses conceitos fundamentais.

Baixar a Apostila Completa 📥

Lendo o Log: Onde exatamente está o erro?

O PHP te dá a resposta exata de onde você errou, basta ler a mensagem do terminal (ou da tela) com atenção. O erro sempre tem duas partes fundamentais:

Warning: Cannot modify header information - headers already sent by (output started at /var/www/config.php:5) in /var/www/login.php on line 12

  • output started at config.php:5 - Este é o CULPADO. Vá no arquivo config.php, exatamente na linha 5. É lá que existe um espaço, um echo ou um HTML perdido.
  • in login.php on line 12 - Esta é a VÍTIMA. É onde está a sua função header() que falhou porque o arquivo config.php estragou tudo antes.

Onde isso quebra na vida real?

Você vai esbarrar nisso constantemente ao criar Sistemas de Login (onde você checa as credenciais e redireciona para a área restrita), ao forçar Downloads de Arquivos (onde você altera o Content-Type via header), e ao manipular Cookies ou Sessões (session_start() também modifica cabeçalhos e obedece às mesmas regras).

Dica de Ouro do Sênior: O vilão invisível "UTF-8 BOM"

Você olhou o arquivo inteiro. Não tem espaço, não tem enter, não tem echo, e o erro continua. O que está acontecendo?

O seu editor de código (como o Bloco de Notas do Windows ou configurações erradas no VSCode) pode estar salvando o arquivo com a codificação UTF-8 com BOM (Byte Order Mark). O BOM insere 3 bytes invisíveis no mesmíssimo início do arquivo. O PHP lê esses bytes, acha que é conteúdo, e despacha os cabeçalhos. Mude a codificação do seu editor para UTF-8 Sem BOM (ou UTF-8 genérico) e salve novamente. O erro sumirá.

Como evitar dor de cabeça

  • Remova qualquer quebra de linha antes de <?php.
  • Se um arquivo PHP contém apenas código (sem HTML), nunca feche a tag ?> no final. Deixar aberto impede que espaços acidentais no fim do arquivo causem o erro ao ser incluído via require.
  • Use ob_start() no topo do seu projeto (como no `index.php` principal) se a sua arquitetura misturar muita visualização com lógica de controlador.
  • Sempre verifique a codificação UTF-8 sem BOM.

Corrigir bugs rapidamente é o que separa o amador do profissional. Agora que você dominou a lógica do protocolo HTTP e do PHP, avance em seus estudos acessando o Sumário Completo do Curso PHP Progressivo e estude todos os módulos, do básico ao avançado com MySQL.

Nenhum comentário:

Veja também: