Pregunta Cómo reparar el error "Encabezados ya enviados" en PHP


Cuando ejecuto mi script, recibo varios errores como este:

Advertencia: no se puede modificar la información del encabezado: encabezados ya enviados por (la salida comenzó en /some/file.php:12) en /some/file.php en línea 23

Las líneas mencionadas en los mensajes de error contienen header() y setcookie() llamadas.

¿Cuál podría ser la razón de ésto? ¿Y como arreglarlo?


836
2017-11-06 17:45


origen


Respuestas:


¡Sin salida antes de enviar encabezados!

Las funciones que envían / ​​modifican encabezados HTTP deben invocarse antes de que se haga cualquier salida. resumen ⇊ De lo contrario, la llamada falla:

Advertencia: No se puede modificar la información del encabezado: los encabezados ya enviados (la salida comenzó en guión: línea)

Algunas funciones que modifican el encabezado HTTP son:

La salida puede ser:

  • Involuntario:

  • Intencional:

    • print, echo y otras funciones que producen resultados
    • Crudo <html> secciones anteriores <?php código.

¿Por que sucede?

Para entender por qué los encabezados deben enviarse antes de la salida, es necesario mirar un típico HTTP respuesta. Los scripts PHP principalmente generan contenido HTML, pero también pasan un conjunto de encabezados HTTP / CGI para el servidor 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>

La página / salida siempre sigue los encabezados PHP tiene que pasar el encabezados al servidor web primero. Solo puede hacer eso una vez. Después del doble salto de línea, nunca podrá enmendarlos más.

Cuando PHP recibe la primera salida (print, echo, <html>) va a enjuagar todos los encabezados recogidos. Luego puede enviar toda la salida quiere. Pero enviar más encabezados HTTP es imposible entonces.

¿Cómo puede saber dónde se produjo la producción prematura?

los header() advertencia contiene toda la información relevante para localizar la causa del problema:

Advertencia: No se puede modificar la información del encabezado: los encabezados ya enviados por    (la salida comenzó en / www / usr2345 / htdocs /auth.php: 52) en   /www/usr2345/htdocs/index.php en la línea 100

Aquí "línea 100" se refiere a la secuencia de comandos donde el header()  invocación ha fallado.

Los "salida comenzó en"nota dentro del paréntesis es más significativo. Denomina la fuente de salida anterior. En este ejemplo, es auth.php y línea 52. Ahí es donde tienes que buscar resultados prematuros.

Causas típicas:

  1. Imprimir, eco

    Salida intencional de print y echo declaraciones terminarán la oportunidad de enviar encabezados HTTP. El flujo de la aplicación debe ser reestructurado para evitar eso. Utilizar funciones y esquemas de plantillas. Asegurar header() las llamadas ocurren antes de mensajes están escritos.

    Las funciones que producen salida incluyen

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


     entre otros y funciones definidas por el usuario.

  2. Áreas HTML sin formato

    Secciones de HTML sin analizar en una .php archivo son salida directa también. Condiciones de script que desencadenarán header() la llamada debe ser notada antes de alguna crudo <html> bloques.

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

    Use un esquema de plantillas para separar el procesamiento de la lógica de salida.

    • Coloque el código de procesamiento de formularios encima de los scripts.
    • Use variables de cadena temporales para aplazar los mensajes.
    • La lógica de salida real y la salida de HTML entremezclado deberían ser las últimas.

  3. Espacio en blanco antes <?php para "script.php" línea 1"advertencias"

    Si la advertencia se refiere a la salida en línea 1, entonces es principalmente líder espacio en blanco, texto o HTML antes de la apertura <?php simbólico.

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

    De manera similar, puede ocurrir para scripts adjuntos o secciones de scripts:

    ?>
    
    <?php
    

    PHP realmente come un soltero linebreak después de cerrar las etiquetas. Pero no lo hará Compensar múltiples líneas nuevas o pestañas o espacios desplazados en tales espacios.

  4. UTF-8 BOM

    Los saltos de línea y los espacios solos pueden ser un problema. Pero también hay "invisibles" secuencias de caracteres que pueden causar esto. Más famoso el UTF-8 BOM (Byte-Order-Mark) que no se muestra en la mayoría de los editores de texto. Es la secuencia de bytes EF BB BF, cual es opcional y redundante para documentos codificados UTF-8. PHP sin embargo tiene que tratar como salida sin procesar. Puede aparecer como los personajes  en la salida (si el cliente interpreta el documento como Latin-1) o similar "basura".

    En particular, los editores gráficos y los IDE basados ​​en Java son ajenos a su presencia. No lo visualizan (obligado por el estándar Unicode). Sin embargo, la mayoría de los editores de programadores y consolas:

    joes editor showing UTF-8 BOM placeholder, and MC editor a dot

    Allí es fácil reconocer el problema desde el principio. Otros editores pueden identificar su presencia en un archivo / menú de configuración (Notepad ++ en Windows puede identificar y remediar el problema), Otra opción para inspeccionar la presencia de listas de materiales es recurrir a un Hexeditor. En sistemas * nix hexdump por lo general está disponible, si no es una variante gráfica que simplifica la auditoría de estos y otros problemas:

    beav hexeditor showing utf-8 bom

    Una solución fácil es configurar el editor de texto para guardar archivos como "UTF-8 (sin BOM)" o similar nomenclatura. A menudo los recién llegados recurren a la creación de nuevos archivos y simplemente copie y pegue el código anterior en.

    Utilidades de corrección

    También hay herramientas automatizadas para examinar y reescribir archivos de texto (sed/awk o recode) Para PHP específicamente está el phptags etiqueta más ordenada. Reescribe etiquetas cercanas y abiertas en formas largas y cortas, pero también fácilmente corrige los problemas de espacio en blanco inicial y final, Unicode y UTF-x BOM:

    phptags  --whitespace  *.php
    

    Es sensato usarlo en un directorio completo de inclusión o proyecto.

  5. Espacios en blanco después ?>

    Si la fuente de error se menciona como detrás del clausura ?> entonces aquí es donde se escribió un espacio en blanco o texto en bruto. El marcador de final de PHP no finaliza la ejecución del script en este punto. Cualquier texto / espacio caracteres después de que se escribirá como contenido de la página todavía.

    Se recomienda comúnmente, en particular a los recién llegados, que detrás ?> PHP las etiquetas de cierre deben ser omitidas. Esta evita una pequeña porción de estos casos. (Muy comunmente include()d los guiones son los culpables).

  6. Fuente de error mencionada como "Desconocido en la línea 0"

    Normalmente es una extensión PHP o una configuración php.ini si no hay un origen de error está concretizado

    • Ocasionalmente es el gzip configuración de codificación de la secuencia o el ob_gzhandler.
    • Pero también podría ser doblemente cargado extension= módulo generando un mensaje de inicio / advertencia PHP implícito.

  7. Mensajes de error anteriores

    Si otra declaración o expresión PHP causa un mensaje de advertencia o notándose que se extiende, que también cuenta como salida prematura.

    En este caso, debe evitar el error, retrasar la ejecución de la declaración, o suprimir el mensaje con, p. isset() o @() - cuando cualquiera de ellos no obstruye la depuración más adelante.

Sin mensaje de error

Si usted tiene error_reporting o display_errors deshabilitado por php.ini, entonces no aparecerá ninguna advertencia. Pero ignorar los errores no hará que el problema vaya lejos. Los encabezados aún no pueden enviarse después de una salida prematura.

Así que cuando header("Location: ...") redirige silenciosamente falla es muy recomendable para sondear las advertencias. Vuelva a habilitarlos con dos comandos simples Encima del script de invocación:

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

O set_error_handler("var_dump"); si todo lo demás falla.

Hablando de encabezados de redirección, a menudo deberías usar un modismo como esto para las rutas de código finales:

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

Preferiblemente incluso una función de utilidad, que imprime un mensaje de usuario en caso de header() fallas

Buffer de salida como solución

PHP buffer de salida es una solución para aliviar este problema. A menudo funciona de manera confiable, pero no debería sustituye la estructuración adecuada de la aplicación y separa la salida del control lógica. Su objetivo real es minimizar las transferencias fragmentadas al servidor web.

  1. los output_buffering= establecer sin embargo puede ayudar. Configurarlo en php.ini o vía .htaccess o incluso .user.ini en configuraciones modernas de FPM / FastCGI.
    Habilitarlo permitirá a PHP almacenar el buffer de salida en lugar de pasarlo al servidor web instantáneamente. PHP por lo tanto puede agregar encabezados HTTP.

  2. También se puede entablar con una llamada a ob_start(); Encima del script de invocación. Sin embargo, es menos confiable por varias razones:

    • Incluso si <?php ob_start(); ?> inicia el primer script, espacio en blanco o un BOM podría mezclarse antes, haciéndolo ineficaz.

    • Puede ocultar espacios en blanco para salida HTML. Pero tan pronto como la aplicación la lógica intenta enviar contenido binario (una imagen generada, por ejemplo), la salida externa amortiguada se convierte en un problema. (Necesitando ob_clean() como otra solución).

    • El búfer tiene un tamaño limitado y puede rebasarse fácilmente cuando se lo deja a los valores predeterminados. Y eso tampoco es una ocurrencia rara, difícil de rastrear cuando sucede.

Por lo tanto, ambos enfoques pueden volverse poco confiables, en particular cuando se cambia entre configuraciones de desarrollo y / o servidores de producción. Por eso, el almacenamiento en búfer de salida es ampliamente considerado como una muleta / estrictamente una solución.

Ver también el ejemplo de uso básico en el manual, y para más ventajas y desventajas:

Pero funcionó en el otro servidor?

Si no recibió la advertencia de encabezados antes, entonces buffer de salida  Configuración de php.ini  ha cambiado. Es probable que no esté configurado en el servidor actual / nuevo.

Comprobando con headers_sent()

Siempre puedes usar headers_sent() para sondear si aún es posible ... enviar encabezados. Lo cual es útil para imprimir condicionalmente una información o aplicar otra lógica alternativa.

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

Las soluciones alternativas de respaldo son:

  • HTML <meta> etiqueta

    Si su aplicación es estructuralmente difícil de solucionar, entonces es fácil (pero un tanto poco profesional) forma de permitir redirecciones es inyectar un HTML <meta> etiqueta. Se puede lograr una redirección con:

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

    O con un breve retraso:

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

    Esto conduce a HTML no válido cuando se utiliza pasado el <head> sección. La mayoría de los navegadores aún lo aceptan.

  • Redirigir JavaScript

    Como alternativa a Redirigir JavaScript se puede usar para redirecciones de página:

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

    Si bien esto a menudo es más compatible con HTML que el <meta> solución, incurre en dependencia de los clientes compatibles con JavaScript.

Ambos enfoques, sin embargo, hacen retrocesos aceptables cuando el encabezado HTTP genuino () las llamadas fallan Idealmente, siempre combinarías esto con un mensaje fácil de usar y enlace clicable como último recurso. (Que por ejemplo es lo que http_redirect () La extensión PECL sí lo hace).

Por qué setcookie() y session_start() también están afectados

Ambos setcookie() y session_start() necesita enviar un Set-Cookie: Encabezado HTTP Por lo tanto, se aplican las mismas condiciones y se generarán mensajes de error similares para situaciones de salida prematura.

(Por supuesto, además se ven afectados por las cookies desactivadas en el navegador, o incluso problemas de proxy. La funcionalidad de la sesión obviamente también depende de la libertad espacio en disco y otras configuraciones de php.ini, etc.)

Otros enlaces


2640
2017-11-06 17:44



Este mensaje de error se activa cuando cualquier cosa se envía antes de enviar encabezados HTTP (con setcookie o header) Razones comunes para generar algo antes de que los encabezados HTTP sean:

  • Espacios en blanco accidentales, a menudo al principio o al final de los archivos, como este:

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

Para evitar esto, simplemente deje fuera el cierre ?> - no se requiere de todos modos.

  • Marcas de orden de bytes al comienzo de un archivo php. Examine sus archivos php con un editor hexadecimal para averiguar si ese es el caso. Deben comenzar con los bytes 3F 3C. Puede eliminar de forma segura la lista de materiales EF BB BF desde el inicio de los archivos.
  • Salida explícita, como llamadas a echo, printf, readfile, passthrucódigo antes <? etc.
  • Una advertencia emitida por php, si el display_errors La propiedad php.ini está establecida. En lugar de fallar en un error del programador, php silenciosamente corrige el error y emite una advertencia. Si bien puedes modificar el display_errors o error al reportar configuraciones, mejor deberías arreglar el problema.
    Los motivos comunes son los accesos a elementos indefinidos de una matriz (como $_POST['input'] sin uso empty o isset para probar si la entrada está configurada), o usando una constante indefinida en lugar de una cadena literal (como en $_POST[input], fíjate en las comillas que faltan).

Encendiendo buffer de salida debería hacer que el problema desaparezca; toda la salida después de la llamada a ob_start se almacena en la memoria hasta que libere el búfer, p. con ob_end_flush.

Sin embargo, aunque el almacenamiento en búfer de salida evita los problemas, debe determinar realmente por qué su aplicación emite un cuerpo HTTP antes del encabezado HTTP. Eso sería como tomar una llamada telefónica y discutir su día y el clima antes de decirle a la persona que llama que tiene el número equivocado.


178
2017-08-01 06:43



He recibido este error muchas veces antes. Y estoy seguro de que todos los programadores de PHP al menos una vez obtuvieron este error. Para resolver este error, puede resolver la solución de uso según su nivel de problema:

Posible solución 1:

Es posible que haya dejado espacios en blanco antes de o después (al final del archivo después de?>) es decir

THERE SHOULD BE NO BLANK SPACES HERE
<?php  

   echo "your code here";

?>
DO CHECK FOR BLANK SPACES HERE AS WELL; THIS LINE (blank line) SHOULD NOT EXIST.

La mayoría de las veces esto debería resolver su problema. Compruebe todos los archivos asociados con el archivo que require.

Nota:  A veces EDITOR (IDE) como gedit (un editor de Linux predeterminado) agrega una línea en blanco en guardar guardar archivo. Esto no debería suceder. Si estás usando linux puede usar el editor VI para eliminar espacios / líneas después de?> al final de la página.

Si este no es tu caso, entonces puedes usar ob_start para el búfer de salida como a continuación:

Posible solución 2:

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

101
2018-03-24 12:54



En lugar de la línea de abajo

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

escribir

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

o

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

Definitivamente resolverá tu problema. Me enfrenté al mismo problema, pero lo resolví escribiendo la ubicación del encabezado de la manera anterior.


73
2017-11-06 17:45



Tú lo haces

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

antes de configurar las cookies, lo cual no está permitido. No puede enviar ningún resultado antes de los encabezados, ni siquiera una línea en blanco.


38
2017-11-06 17:45



Es por esta línea:

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

Usted no debe imprimir / eco cualquier cosa antes de enviar los encabezados.


29
2018-05-16 20:37



Un consejo sencillo: un espacio simple (o char especial invisible) en su secuencia de comandos, justo antes de la primera <?php etiqueta, puede causar esto! Especialmente cuando trabajas en un equipo y alguien usa un IDE "débil" o se ha metido en los archivos con extraños editores de texto.

He visto estas cosas;)


25
2017-11-08 01:29



utilizar

ob_start ();

en la parte superior de tu script, y

ob_end_flush ();

en la parte inferior de tu script Esto activará el almacenamiento en búfer de salida y sus encabezados se crearán después de que la página esté almacenada en búfer.

PROBLEMAS COMUNES:

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

(respuesta copiada de:fuente)

1) no debería haber ningún resultado (es decir echo.. o códigos HTML) antes de la header(.......); mando.

2) eliminar cualquier espacio en blanco(o nueva línea) antes de <?php y después ?> etiquetas.

3)  ¡REGLA DE ORO! - compruebe si ese archivo php (y también, si include otros archivos) tienen UTF8 sin BOM codificación (y no solo UTF-8) Eso es un problema en muchos casos (porque UTF8 el archivo codificado tiene un carácter especial en el inicio del archivo php, que el editor de texto no muestra) !!!!!!!!!!!

4) Después header(...); debes usar exit; 

5)  siempre use la referencia 301 o 302:

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

6)  Active el informe de errores. Y di el error.

7) Si ninguna de las anteriores ayuda, utilice la redirección JAVSCRIPT (sin embargo, método fuertemente no recomendado), puede ser la última oportunidad en casos personalizados ...:

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

22