Como corrigir o erro "Cabeçalhos já enviados" no PHP


831

Ao executar meu script, estou recebendo vários erros como este:

Aviso: Não é possível modificar as informações do cabeçalho - os cabeçalhos já enviados por ( saída iniciada em /some/file.php:12 ) em /some/file.php na linha 23

As linhas mencionadas nas mensagens de erro contêm header()e setcookie()chama.

Qual poderia ser a razão disso? e como consertar isso?



Verifique se nenhum texto foi produzido ( ob_starte ob_end_clean() pode ser útil aqui). Você pode então definir um cookie ou sessão igual a ob_get_contents()e depois usar ob_end_clean()para limpar o buffer.
Jack Tuck

Utilizar a safeRedirectfunção no meu Biblioteca PHP: github.com/heinkasner/PHP-Library/blob/master/extra.php
heinkasner

5
~~~~~~~~~~ sua codificação de arquivo não deve ser UTF-8, mas UTF-8 (Without BOM)~~~~~~~~~~~
T.Todua

Respostas:


2997

Nenhuma saída antes de enviar cabeçalhos!

As funções que enviam / modificam cabeçalhos HTTP devem ser chamadas antes que qualquer saída seja feita . summary ⇊ Caso contrário, a chamada falhará:

Aviso: Não é possível modificar as informações do cabeçalho - cabeçalhos já enviados (saída iniciada no script: linha )

Algumas funções que modificam o cabeçalho HTTP são:

A saída pode ser:

  • Não intencional:

  • Intencional:

    • print, echoE outras funções de produção de saída
    • Matérias- <html>seções antes <?phpde código.

Por que isso acontece?

Para entender por que os cabeçalhos devem ser enviados antes da saída, é necessário analisar uma resposta HTTP típica . Os scripts PHP geram principalmente conteúdo HTML, mas também transmitem um conjunto de cabeçalhos HTTP / CGI para o servidor da web:

HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8

<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="/"> <img src=internal-icon-delayed> </a>

A página / saída sempre segue os cabeçalhos. O PHP precisa passar os cabeçalhos para o servidor da web primeiro. Só pode fazer isso uma vez. Após a quebra de linha dupla, ele nunca mais poderá alterá-los.

Quando o PHP recebe a primeira saída ( print, echo, <html>) vai expulsar todos os cabeçalhos recolhidos. Depois, ele pode enviar toda a saída que desejar. Mas enviar cabeçalhos HTTP adicionais é impossível então.

Como você pode descobrir onde ocorreu a saída prematura?

O header()aviso contém todas as informações relevantes para localizar a causa do problema:

Aviso: Não é possível modificar as informações do cabeçalho - os cabeçalhos já enviados por (saída iniciada em / www / usr2345 / htdocs / auth.php: 52 ) em /www/usr2345/htdocs/index.php na linha 100

Aqui "linha 100" refere-se ao script em que a header() chamada falhou.

A nota " saída iniciada em " entre parênteses é mais significativa. Denomina a fonte da saída anterior. Neste exemplo, é auth.php e linha52 . É aí que você precisa procurar resultados prematuros.

Causas típicas:

  1. Imprimir, eco

    A saída intencional de printe echoinstruções encerrará a oportunidade de enviar cabeçalhos HTTP. O fluxo do aplicativo deve ser reestruturado para evitar isso. Use funções e esquemas de modelos. Verifique se as header()chamadas ocorrem antes que as mensagens sejam gravadas.

    As funções que produzem saída incluem

    • print, echo, printf,vprintf
    • trigger_error, ob_flush, ob_end_flush, var_dump,print_r
    • readfile, passthru, flush, imagepng,imagejpeg


    entre outros e funções definidas pelo usuário.

  2. Áreas HTML brutas

    Seções HTML não analisadas em um .phparquivo também são saída direta. As condições de script que acionarão uma header()chamada devem ser observadas antes de qualquer<html> bloco bruto .

    <!DOCTYPE html>
    <?php
        // Too late for headers already.

    Use um esquema de modelo para separar o processamento da lógica de saída.

    • Coloque o código de processamento do formulário no topo dos scripts.
    • Use variáveis ​​de string temporárias para adiar mensagens.
    • A lógica de saída real e a saída HTML misturada devem seguir por último.

  3. <?phpEspaço em branco antes para avisos "script.php line 1 "

    Se o aviso se referir à saída em linha 1, é principalmente espaço em branco , texto ou HTML antes do <?phptoken de abertura .

     <?php
    # There's a SINGLE space/newline before <? - Which already seals it.

    Da mesma forma, isso pode ocorrer para scripts anexados ou seções de script:

    ?>
    
    <?php

    Na verdade, o PHP consome uma única quebra de linha após fechar tags. Mas não compensará várias novas linhas, guias ou espaços alterados para essas lacunas.

  4. BOM UTF-8

    Quebras de linha e espaços por si só podem ser um problema. Mas também existem seqüências de caracteres "invisíveis" que podem causar isso. O mais famoso é o UTF-8 BOM (Byte-Order-Mark), que não é exibido pela maioria dos editores de texto. É a sequência de bytes EF BB BF, que é opcional e redundante para documentos codificados em UTF-8. O PHP, no entanto, deve tratá-lo como saída bruta. Pode aparecer como os caracteres na saída (se o cliente interpretar o documento como latino-1) ou "lixo" semelhante.

    Em particular, editores gráficos e IDEs baseados em Java são alheios à sua presença. Eles não o visualizam (obrigados pelo padrão Unicode). A maioria dos editores de programadores e consoles, no entanto, faz:

    joes editor mostrando o espaço reservado UTF-8 BOM e MC editor um ponto

    É fácil reconhecer o problema desde o início. Outros editores podem identificar sua presença em um menu de arquivo / configurações (o Notepad ++ no Windows pode identificar e solucionar o problema ). Outra opção para inspecionar a presença das listas técnicas está recorrendo a um hexeditor . Em sistemas * nix hexdumpgeralmente está disponível, se não uma variante gráfica que simplifica a auditoria desses e de outros problemas:

    hexeditor beav mostrando utf-8 bom

    Uma solução fácil é configurar o editor de texto para salvar arquivos como "UTF-8 (sem BOM)" ou uma nomenclatura semelhante. Geralmente, os recém-chegados recorrem à criação de novos arquivos e apenas copiam e colam o código anterior novamente.

    Utilitários de correção

    Também existem ferramentas automatizadas para examinar e reescrever arquivos de texto ( sed/awk ou recode). Para PHP especificamente, há a phptagstag mais arrumada . Ele reescreve as tags fechadas e abertas em formas longas e curtas, mas também corrige facilmente problemas de espaço em branco à esquerda e à direita, Unicode e UTF-x BOM:

    phptags  --whitespace  *.php

    É sensato usar em um diretório inteiro de inclusão ou projeto.

  5. Espaço em branco depois ?>

    Se a fonte do erro for mencionada como atrás do fechamento?> , é aqui que alguns espaços em branco ou texto bruto serão gravados. O marcador final do PHP não termina a execução do script neste momento. Quaisquer caracteres de texto / espaço depois dele serão gravados como conteúdo da página.

    É geralmente recomendado, em particular para os novatos, que as ?>tags de fechamento do PHP à direita sejam omitidas. Isso evita uma pequena parte desses casos. (Geralmente, os include()dscripts são os culpados.)

  6. Origem do erro mencionada como "Desconhecido na linha 0"

    Geralmente, é uma extensão do PHP ou configuração do php.ini se nenhuma fonte de erro for concretizada.

    • Ocasionalmente, é a gzipconfiguração de codificação de fluxo ou oob_gzhandler .
    • Mas também pode ser qualquer extension=módulo duplamente carregado que gere uma mensagem implícita de inicialização / aviso do PHP.

  7. Mensagens de erro anteriores

    Se outra instrução ou expressão PHP causar a impressão de uma mensagem ou aviso de aviso, isso também conta como saída prematura.

    Nesse caso, você precisa evitar o erro, atrasar a execução da instrução ou suprimir a mensagem com, por exemplo, isset()ou @()- quando um deles não obstrui a depuração posteriormente.

Nenhuma mensagem de erro

Se você tiver error_reportingou display_errorsdesativado por php.ini, nenhum aviso será exibido. Mas ignorar erros não fará com que o problema desapareça. Cabeçalhos ainda não podem ser enviados após saída prematura.

Portanto, quando os header("Location: ...")redirecionamentos falham silenciosamente, é aconselhável verificar se há avisos. Reative-os com dois comandos simples no topo do script de chamada:

error_reporting(E_ALL);
ini_set("display_errors", 1);

Ou set_error_handler("var_dump");se tudo mais falhar.

Falando em cabeçalhos de redirecionamento, você deve usar um idioma como este para os caminhos finais do código:

exit(header("Location: /finished.html"));

De preferência, mesmo uma função de utilitário, que imprime uma mensagem do usuário em caso de header()falhas.

Buffer de saída como solução alternativa

O buffer de saída do PHP é uma solução alternativa para aliviar esse problema. Geralmente funciona de maneira confiável, mas não deve substituir a estruturação adequada do aplicativo e a separação da saída da lógica de controle. Seu objetivo real é minimizar as transferências fragmentadas para o servidor da web.

  1. A output_buffering= configuração, no entanto, pode ajudar. Configure-o no php.ini ou via .htaccess ou mesmo .user.ini nas configurações modernas do FPM / FastCGI.
    Ativá-lo permitirá que o PHP armazene em buffer a saída em vez de passá-la ao servidor da web instantaneamente. Assim, o PHP pode agregar cabeçalhos HTTP.

  2. Da mesma forma, ele pode ser envolvido com uma chamada para o ob_start(); topo do script de chamada. No entanto, o que é menos confiável por vários motivos:

    • Mesmo que <?php ob_start(); ?>o primeiro script seja iniciado, o espaço em branco ou uma BOM podem ser embaralhados antes, tornando-o ineficaz .

    • Pode ocultar espaços em branco para a saída HTML. Mas assim que a lógica do aplicativo tenta enviar conteúdo binário (uma imagem gerada, por exemplo), a saída estranha em buffer se torna um problema. ( ob_clean() Necessário como solução alternativa mais avançada.)

    • O tamanho do buffer é limitado e pode exceder facilmente quando deixado como padrão. E isso também não é uma ocorrência rara, difícil de rastrear quando acontece.

Portanto, ambas as abordagens podem se tornar não confiáveis ​​- principalmente ao alternar entre configurações de desenvolvimento e / ou servidores de produção. É por isso que o buffer de saída é amplamente considerado apenas uma muleta / estritamente uma solução alternativa.

Veja também o exemplo de uso básico no manual e para mais prós e contras:

Mas funcionou no outro servidor !?

Se você não recebeu um aviso dos cabeçalhos antes, a configuração do buffer de saída do php.ini foi alterada. Provavelmente não está configurado no servidor atual / novo.

Verificando com headers_sent()

Você sempre pode usar headers_sent()para investigar se ainda é possível ... enviar cabeçalhos. O que é útil para imprimir condicionalmente uma informação ou aplicar outra lógica de fallback.

if (headers_sent()) {
    die("Redirect failed. Please click on this link: <a href=...>");
}
else{
    exit(header("Location: /user.php"));
}

Soluções alternativas úteis são:

  • <meta>Tag HTML

    Se seu aplicativo for estruturalmente difícil de corrigir, uma maneira fácil (mas um pouco não profissional) de permitir redirecionamentos é injetar uma <meta>tag HTML . É possível obter um redirecionamento com:

     <meta http-equiv="Location" content="http://example.com/">

    Ou com um pequeno atraso:

     <meta http-equiv="Refresh" content="2; url=../target.html">

    Isso leva ao HTML inválido quando utilizado após a <head>seção. A maioria dos navegadores ainda o aceita.

  • Redirecionamento de JavaScript

    Como alternativa, um redirecionamento JavaScript pode ser usado para redirecionamentos de página:

     <script> location.replace("target.html"); </script>

    Embora geralmente seja mais compatível com HTML do que a <meta>solução alternativa, incorre em dependência de clientes compatíveis com JavaScript.

Ambas as abordagens, no entanto, fazem fallbacks aceitáveis ​​quando as chamadas genuínas de cabeçalho HTTP () falham. Idealmente, você sempre combinaria isso com uma mensagem amigável e um link clicável como último recurso. (Que, por exemplo, é o que a extensão PECL http_redirect () faz.)

Por que setcookie()e session_start()também são afetados

Ambos setcookie()e session_start()precisam enviar um Set-Cookie:cabeçalho HTTP. Portanto, as mesmas condições se aplicam e mensagens de erro semelhantes serão geradas para situações de saída prematura.

(É claro que eles também são afetados por cookies desabilitados no navegador ou até mesmo por problemas de proxy. A funcionalidade da sessão obviamente também depende do espaço livre em disco e de outras configurações do php.ini, etc.)

Links adicionais


O notepad.exe também é complicado. Normalmente, uso o NetBeans que não adiciona BOM, mesmo que o arquivo esteja codificado. A edição posterior de um arquivo no bloco de notas atrapalha as coisas, especialmente no IIS como servidor da web. Parece que o apache descarta a lista técnica (adicionada convencionalmente).
Teson

4
Remover o fechamento ?>do final de um arquivo php geralmente é uma boa prática que ajuda a minimizar esses erros também. Espaço em branco indesejado não ocorrerá no final dos arquivos, e você ainda poderá adicionar cabeçalhos à resposta posteriormente. Também é útil se você usar o buffer de saída e não desejar adicionar espaços em branco indesejados no final das partes geradas pelos arquivos incluídos.
Nikita #

Estranho, mudei meu arquivo do cPanel Linux Hosting para o VPS. Antes estava funcionando corretamente, mas aqui mostrava esse erro (eu tinha algum código html antes do cabeçalho). Por quê?
Pablo Escobar

@Purushotamrawat Você leu a parte sobre " Mas funcionou no outro servidor !? "
mario

1
@PeterSMcIntyre A BOM UTF8 presumivelmente (corrige isso) / nenhum buffer de saída está ativado (não confie nisso).
Mario

199

Essa mensagem de erro é acionada quando qualquer coisa é enviada antes de você enviar cabeçalhos HTTP (com setcookieou header). Os motivos comuns para a saída de algo antes dos cabeçalhos HTTP são:

  • Espaço em branco acidental, geralmente no início ou no final dos arquivos, assim:

     <?php
    // Note the space before "<?php"
    ?>

       Para evitar isso, basta deixar de fora o fechamento ?>- não é necessário de qualquer maneira.

  • Marcas de ordem de bytes no início de um arquivo php. Examine seus arquivos php com um editor hexadecimal para descobrir se é esse o caso. Eles devem começar com os bytes 3F 3C. Você pode remover com segurança a lista técnica EF BB BFdesde o início dos arquivos.
  • Saída explícito, tais como chamadas para echo, printf, readfile, passthru, código antes <?etc.
  • Um aviso emitido pelo php, se a display_errorspropriedade php.ini estiver configurada. Em vez de travar com um erro de programador, o php corrige silenciosamente o erro e emite um aviso. Enquanto você pode modificar as configurações display_errorsou error_reporting , você deve corrigir o problema.
    Razões comuns são acessos a elementos indefinidos de uma matriz (como $_POST['input']sem usar emptyou issetpara testar se a entrada está configurada) ou usar uma constante indefinida em vez de uma string literal (como $_POST[input], observe as aspas ausentes).

Ativar o buffer de saída deve resolver o problema; toda a saída após a chamada para ob_starté armazenada em buffer na memória até você liberar o buffer, por exemplo, com ob_end_flush.

No entanto, embora o buffer de saída evite os problemas, você realmente deve determinar por que seu aplicativo gera um corpo HTTP antes do cabeçalho HTTP. Seria como atender um telefonema e discutir o seu dia e o clima antes de dizer ao chamador que ele está com o número errado.


sua ajuda me obrigado #
31419 Vishwa Pratap

122

Eu recebi esse erro muitas vezes antes e tenho certeza de que todos os programadores PHP receberam esse erro pelo menos uma vez antes.

Possível solução 1

Este erro pode ter sido causado pelos espaços em branco antes do início do arquivo ou após o final do arquivo. Esses espaços em branco não devem estar aqui.

ex) NÃO DEVERÁ ESPAÇOS EM BRANCO

   echo "your code here";

?>
THERE SHOULD BE NO BLANK SPACES HERE

Verifique todos os arquivos associados ao arquivo que causa esse erro.

Nota: Às vezes, o EDITOR (IDE), como o gedit (um editor padrão do linux), adiciona uma linha em branco no arquivo salvo. Isso não deveria acontecer. Se você estiver usando Linux. você pode usar o editor VI para remover espaço / linhas após?> no final da página.

Solução possível 2: Se esse não for o seu caso, use ob_start para buffer:

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

Isso ativará o buffer de saída e seus cabeçalhos serão criados após o buffer da página.


18
ob_start()apenas esconde o problema; não o use para resolver esse problema específico.
Ja͢ck 15/05

@ Jack Se eu não uso de ob_start(), em seguida, o que devo fazer para resolver este problema:Headers already sent
Shafizadeh

@ Saraj Se você está recebendo o erro especificamente por causa do editor que está usando, deve mexer nas configurações para impedir que ele cause o problema ou alternar entre editores. Se você estiver recebendo o erro por qualquer outro motivo, leia as respostas nesta pergunta (especificamente a resposta aceita) para descobrir qual é realmente o problema e resolvê-lo.
Samsquanch

3
ob_start()não "esconde" o problema, resolve o problema.
TMS

1
Eu tive esse problema uma quando eu carregar meus arquivos para o servidor, que apoiaram mesmo PHP5.3 Use servidor com PHP 5.6 ou mais
GGSoft

86

Em vez da linha abaixo

//header("Location:".ADMIN_URL."/index.php");

Escreva

echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");

ou

?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php

Definitivamente resolverá seu problema. Eu enfrentei o mesmo problema, mas resolvi através da localização do cabeçalho de escrita da maneira acima.


41

Você faz

printf ("Hi %s,</br />", $name);

antes de definir os cookies, o que não é permitido. Você não pode enviar nenhuma saída antes dos cabeçalhos, nem mesmo uma linha em branco.


32

É por causa desta linha:

printf ("Hi %s,</br />", $name);

Você não deve imprimir / repetir nada antes de enviar os cabeçalhos.


31

PROBLEMAS COMUNS:

(copiado de: fonte )

====================

1) não deve haver nenhuma saída (isto é, echo..códigos HTML) antes do header(.......);comando.

2) remova qualquer espaço em branco (ou nova linha ) antes <?phpe depois das ?>tags.

3) REGRA DOURADA! - verifique se esse arquivo php (e também, se você tiver includeoutros arquivos) tem UTF8 sem codificação BOM (e não apenas UTF-8 ). Esse é um problema em muitos casos (porque o UTF8 arquivo codificado em possui algo especial no início do arquivo php, que seu editor de texto não mostra) !!!!!!!!!!!

4) Depois que header(...);você deve usarexit;

5) sempre use a referência 301 ou 302:

header("location: http://example.com",  true,  301 );  exit;

6) Ative o relatório de erros e encontre o erro. Seu erro pode ser causado por uma função que não está funcionando. Quando você ativa o relatório de erros, sempre deve primeiro corrigir o erro máximo. Por exemplo, pode ser "Aviso: date_default_timezone_get (): não é seguro confiar nas configurações de fuso horário do sistema". - mais abaixo, você verá o erro "cabeçalhos não enviados". Depois de corrigir o erro mais alto (1º), recarregue sua página. Se você ainda tiver erros, corrija novamente o erro mais alto.

7) Se nenhuma das opções acima ajudar, use o redirecionamento JAVSCRIPT (no entanto, método fortemente não recomendado), pode ser a última chance em casos personalizados ...:

echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;

Por que a configuração é explícita 301ou 302importante?
Jānis Elmeris

26

Uma dica simples: um espaço simples (ou caractere especial invisível) em seu script, logo antes da primeira <?phptag, pode causar isso! Especialmente quando você está trabalhando em equipe e alguém está usando um IDE "fraco" ou mexeu nos arquivos com editores de texto estranhos.

Eu já vi essas coisas;)


22

Outra má prática pode invocar esse problema que ainda não foi declarado.

Veja este trecho de código:

<?php
include('a_important_file.php'); //really really really bad practise
header("Location:A location");
?>

As coisas estão bem, certo?

E se "a_important_file.php" for este:

<?php
//some php code 
//another line of php code
//no line above is generating any output
?>

 ----------This is the end of the an_important_file-------------------

Isso não vai funcionar? Por que? Porque já uma nova linha é gerada.

Agora, embora esse não seja um cenário comum, e se você estiver usando uma estrutura MVC que carrega muitos arquivos antes de entregar coisas ao seu controlador? Este não é um cenário incomum. Esteja preparado para isso.

Do PSR-2 2.2:


  • Todos os arquivos PHP DEVEM usar o Unix LF (linefeed) line ending.
  • Todos os arquivos PHP DEVEM terminar com um single blank line.
  • A tag de fechamento?> DEVE ser omittedde arquivos contendoonly php

Acredite em mim, seguir esses padrões pode poupar muitas horas da sua vida :)


2
De acordo com várias normas (Zend por exemplo), você não deve colocar o fechamento ?>tag em qualquer arquivo em qualquer caso, de forma alguma
Daniel W.

Não consigo reproduzir isso no ambiente Windows, pois funciona usando qualquer combinação (adicionando tags de fechamento, espaços em branco, pressionando a tecla Enter, etc.). Parece que esse problema ocorre principalmente em ambientes Linux.
Junior Mayhé

@JuniorM Deve ser reproduzível. Você pode compartilhar o código que estava experimentando em uma essência ou algo parecido?
MD. Sahib Bin Mahboob

Estou no Windows 7, com o Wamp mais recente instalado. Eu acho que esse bug está relacionado a caracteres ocultos no final da linha. O shortcodes.php do meu Wordpress foi o causador do problema. Eu adicionei a este arquivo uma função simples e ele começou a disparar esse erro "cabeçalhos enviados". Comparei meu shortcodes.php com o wordpress 'e estava tudo bem, exceto o CR LF(típico fim de linha do Windows). Eu o resolvo baixando o arquivo original do repositório Wordpress que possui LF(fim de linha do Linux) em vez de CR LFe também mudei minha função para o theme functions.php. Baseado em: bit.ly/1Gh6mzN
Junior Mayhé

@ Saib, observe que ainda não consigo reproduzir o que é declarado nesta resposta. A resposta é totalmente boa para o ambiente Linux. Testei coisas em branco no meio ?> <?php, removendo e adicionando uma única linha em branco, adicionando e omitindo a marca de fechamento ?>. No Windows + Wamp, todas essas combinações funcionam bem. Wierd ...
Junior Mayhé

15

Às vezes, quando o processo dev possui estações de trabalho WIN e sistemas LINUX (hospedagem) e no código você não vê nenhuma saída antes da linha relacionada, pode ser a formatação do arquivo e a falta do final da linha Unix LF (linefeed) .

O que geralmente fazemos para corrigir rapidamente isso é renomear o arquivo e, no sistema LINUX, criar um novo arquivo em vez do renomeado e, em seguida, copiar o conteúdo para ele. Muitas vezes, isso resolve o problema, pois alguns dos arquivos criados no WIN uma vez movidos para a hospedagem causam esse problema.

Essa correção é fácil para sites gerenciados por FTP e, às vezes, pode economizar algum tempo para nossos novos membros da equipe.


2

Geralmente, esse erro ocorre quando enviamos o cabeçalho após eco ou impressão. Se esse erro ocorrer em uma página específica, verifique se a página não está ecoando nada antes de ligar para start_session().

Exemplo de erro imprevisível:

 <?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();

//your page content

Mais um exemplo:

<?php
includes 'functions.php';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();

//your page content

Conclusão: Não produza nenhum caractere antes de chamar session_start()ou header()funciona nem mesmo em espaço em branco ou em nova linha

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.