Introdução: "Você já enviou algo para a tela, e eu não consigo"
\nSe você já viu no seu site, em vez de uma página bonita, uma tela branca com a mensagem assustadora Warning: Cannot modify header information - headers already sent — você não está sozinho. Este é, talvez, um dos erros mais populares entre desenvolvedores PHP iniciantes (e não só). No Stack Overflow, essa pergunta acumulou centenas de milhares de visualizações, e a quantidade de cópias de código incorreto no mundo é medida em terabytes.
Mas a boa notícia é que o erro "Headers already sent" não é uma maldição, mas sim um lembrete severo do PHP: "Ei, você já começou a enviar código HTML e agora está tentando modificar os cabeçalhos HTTP. Isso não é permitido!".
\nNeste artigo, vamos analisar por que ocorre o erro headers already sent no PHP, como encontrá-lo e, o mais importante, como corrigi-lo de uma vez por todas. Vamos lá!
\n\n1. O que são cabeçalhos HTTP e por que eles "já foram enviados"?
\nAntes de mergulhar no código, vamos entender de forma simples o que acontece "por baixo dos panos". Quando um script PHP é executado, ele primeiro envia os cabeçalhos HTTP (header) para o navegador. Eles contêm informações de serviço: tipo de conteúdo (Content-Type), cookies (Set-Cookie), redirecionamentos (Location), status da resposta (200, 404, 301) e assim por diante.
E somente após todos os cabeçalhos é que começa o envio do corpo do documento — o próprio HTML que você vê na página. O PHP permite modificar os cabeçalhos apenas até o momento em que o primeiro byte de conteúdo é enviado.
\nAssim que você exibe algo na tela (através de echo, print, var_dump ou até mesmo um espaço antes de <?php), o PHP considera que os cabeçalhos já foram enviados. Qualquer tentativa de chamar header(), setcookie() ou session_start() depois disso resulta em um erro fatal.
1.1. Exemplo clássico do erro
\n<?php\necho "Olá, mundo!";\n// Opa! Já exibimos algo.\nheader("Location: https://example.com");\n// Warning: Cannot modify header information - headers already sent\n?>\nNeste exemplo, o echo envia texto para o corpo do documento. Depois disso, o PHP não pode sobrescrever os cabeçalhos para fazer um redirecionamento. Tudo faz sentido.
2. Top 5 causas do "Headers already sent"
\nO erro pode ser causado não apenas por um echo explícito. Aqui estão os cenários mais comuns que pegam até desenvolvedores experientes:
- \n
- Espaço ou linha em branco antes de
<?php— o "bug" mais popular. Se no arquivo, antes da tag de abertura, houver pelo menos um espaço, ele será enviado para a saída. \n - Caracteres invisíveis BOM (Byte Order Mark) — o arquivo foi salvo na codificação UTF-8 with BOM. Os primeiros 3 bytes (EF BB BF) são considerados saída. \n
- Saída de arquivos incluídos — no arquivo
config.phphá um espaço extra após?>. \n - Erros e avisos — se o PHP exibe um aviso (por exemplo, sobre o uso de uma variável não definida), isso também é considerado envio de conteúdo. \n
- Funções
print,printf,var_dumpantes de header() — qualquer função de saída quebra os cabeçalhos. \n
3. Como encontrar a origem do problema: 3 métodos
\nAntes de corrigir, é preciso encontrar de onde vem a saída "extra". Use um destes métodos.
\n\n3.1. Ative a exibição de todos os erros
\nAdicione no início do script (antes de qualquer saída):
\n<?php\nerror_reporting(E_ALL);\nini_set('display_errors', 1);\n?>\nO PHP frequentemente mostra a linha exata onde a saída ocorreu. Procure por uma mensagem como Output started at /caminho/para/arquivo.php:12.
3.2. Use a função error_get_last()
\nVocê pode capturar o último erro