funciona - Cómo corregir el error de "Encabezados ya enviados" en PHP
php header location); (11)
Cuando ejecuto mi script, recibo varios errores como este:
Advertencia: No se puede modificar la información del encabezado: los encabezados ya enviados por (la salida comenzó en /some/file.php:12 ) en /some/file.php en la línea 23
Las líneas mencionadas en los mensajes de error contienen llamadas de header()
y setcookie()
.
¿Cuál podría ser la razón de ésto? ¿Y como arreglarlo?
PROBLEMAS COMUNES:
(Copiado de: source )
====================
1) no debe haber ninguna salida (es decir, echo..
o códigos HTML) antes del header(.......);
mando.
2) eliminar cualquier espacio en blanco (o nueva línea ) antes de las etiquetas <?php
and after ?>
.
3) REGLA DE ORO! - compruebe si ese archivo php (y también, si include
otros archivos) tiene UTF8 sin codificación BOM (y no solo UTF-8 ). Eso es un problema en muchos casos (porque el archivo codificado en UTF8 tiene un carácter especial al inicio del archivo php, que su editor de texto no muestra) !!!!!!!!!!!
4) Después del header(...);
debes usar exit;
5) siempre use referencia 301 o 302:
header("location: http://example.com", true, 301 ); exit;
6) Active el informe de errores. Y dile el error.
7) Si ninguno de los anteriores ayuda, use la redirección de JAVSCRIPT (sin embargo, es un método altamente no recomendado), puede ser la última oportunidad en casos personalizados ...:
echo "<script type=''text/javascript''>window.top.location=''http://website.com/'';</script>"; exit;
No hay salida antes de enviar encabezados!
Las funciones que envían / modifican los encabezados HTTP deben invocarse antes de realizar cualquier salida . resumen ⇊ De lo contrario, la llamada falla:
Advertencia: no se puede modificar la información del encabezado: los encabezados ya se enviaron (la salida se inició en el script: línea )
Algunas funciones que modifican el encabezado HTTP son:
La salida puede ser:
Involuntario:
- Los espacios en blanco antes de
<?php
o después?>
- La marca de orden de bytes UTF-8 específicamente
- Mensajes de error anteriores o avisos
- Los espacios en blanco antes de
Intencional:
-
print
,echo
y otras funciones que producen salida. - Raw
<html>
secciones anteriores<?php
code.
-
¿Por que sucede?
Para comprender por qué se deben enviar los encabezados antes de la salida, es necesario observar una respuesta HTTP típica. Los scripts PHP generan principalmente contenido HTML, pero también pasan un conjunto de encabezados HTTP / CGI al 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 los encabezados al servidor web primero. Solo puede hacer eso una vez. Después de la doble racha, nunca más podrá enmendarlos.
Cuando PHP recibe la primera salida ( print
, echo
, <html>
), vaciará todos los encabezados recopilados. Después puede enviar toda la salida que quiera. Pero enviar más encabezados HTTP es imposible entonces.
¿Cómo puedes saber dónde ocurrió la salida prematura?
La advertencia del header()
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 al script donde la invocación del header()
falló.
La nota de " salida iniciada en " entre paréntesis es más significativa. Se denomina la fuente de salida anterior. En este ejemplo es auth.php
y la línea 52
. Ahí es donde tenías que buscar resultados prematuros.
Causas típicas:
Imprimir, echo
La salida intencional de
print
declaraciones deprint
yecho
terminará la oportunidad de enviar encabezados HTTP. El flujo de aplicación debe ser reestructurado para evitar eso. Utilizar functions y esquemas de plantillas. Asegúrese de que se produzcan llamadas alheader()
antes de que se escriban los mensajes.Las funciones que producen salida incluyen
-
print
,echo
,printf
,vprintf
-
trigger_error
,ob_flush
,ob_end_flush
,var_dump
,print_r
-
readfile
,readfile
,flush
,imagepng
,imagejpeg
Entre otras y funciones definidas por el usuario.-
Áreas HTML sin procesar
Las secciones HTML sin analizar en un archivo
.php
son resultados directos. Las condiciones de script que activarán una llamada deheader()
deben anotarse antes de cualquier bloque<html>
procesar.<!DOCTYPE html> <?php // Too late for headers already.
Utilice 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.
- Utilice variables de cadena temporales para diferir mensajes.
- La lógica de salida real y la salida HTML entremezclada deben seguir en último lugar.
Espacio en blanco antes de
<?php
para las advertencias "script.php line 1 "Si la advertencia se refiere a la salida en la línea
1
, entonces se trata principalmente de espacios en blanco iniciales, texto o HTML antes de la apertura del token<?php
.<?php # There''s a SINGLE space/newline before <? - Which already seals it.
Del mismo modo, puede ocurrir para scripts adjuntos o secciones de script:
?> <?php
PHP en realidad se come un solo salto de línea después de cerrar las etiquetas. Pero no compensará múltiples nuevas líneas o pestañas o espacios cambiados en tales huecos.
UTF-8 BOM
Linebreaks y espacios solo pueden ser un problema. Pero también hay secuencias de caracteres "invisibles" que pueden causar esto. Lo más famoso es 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
, que es opcional y redundante para documentos codificados en UTF-8. PHP sin embargo, tiene que tratarlo como salida en bruto. Puede aparecer como los caracteres
en la salida (si el cliente interpreta el documento como Latin-1) o" basura "similar.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 hacen:
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 solucionar el problema ). Otra opción para inspeccionar la presencia de BOM es recurrir a un hexeditor . En * nix systems
hexdump
suele estar disponible, si no es una variante gráfica que simplifica la auditoría de estos y otros problemas:Una solución fácil es configurar el editor de texto para que guarde los archivos como "UTF-8 (sin lista de materiales)" o una nomenclatura similar. A menudo, los recién llegados recurren a la creación de nuevos archivos y simplemente copian y pegan el código anterior nuevamente.
Utilidades de corrección
También hay herramientas automatizadas para examinar y reescribir archivos de texto ( sed/awk o
recode
). Para PHP específicamente hay la etiqueta phptags tidier . Reescribe las etiquetas de cierre y apertura en formas largas y cortas, pero también corrige fácilmente los problemas de espacios en blanco iniciales y finales, Unicode y UTF-x:phptags --whitespace *.php
Es sensato utilizarlo en un directorio de proyecto o inclusión completo.
¿Espacio en blanco después
?>
Si se menciona el origen del error como detrás del cierre
?>
Aquí es donde se escribieron algunos espacios en blanco o texto en bruto. El marcador final de PHP no termina la ejecución del script en este punto. Todos los caracteres de texto / espacio después de que se escribirán como contenido de la página aún.Se suele recomendar, en particular a los recién llegados, que se deban omitir las etiquetas de cierre
?>
PHP cerrar. Esto evita una pequeña parte de estos casos. (Muy a menudoinclude()d
scripts son los culpables.)Fuente de error mencionada como "Desconocido en la línea 0"
Normalmente es una extensión de PHP o configuración php.ini si no se concreta ninguna fuente de error.
- Ocasionalmente es la configuración de codificación de la secuencia
gzip
o elob_gzhandler
. - Pero también podría ser cualquier
extension=
módulo cargado doblemente que genere un mensaje de advertencia / inicio de PHP implícito.
- Ocasionalmente es la configuración de codificación de la secuencia
Mensajes de error anteriores
Si otra declaración o expresión de PHP provoca que se imprima un mensaje de advertencia o un aviso, eso 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, por ejemplo,
isset()
o@()
, cuando cualquiera de los dos no obstruya la depuración más adelante.
Ningún mensaje de error
Si tiene error_reporting
o display_errors
deshabilitados por php.ini
, no aparecerá ninguna advertencia. Pero ignorar los errores no hará que el problema desaparezca. Los encabezados aún no se pueden enviar después de una salida prematura.
Por lo tanto, cuando el header("Location: ...")
redirige silenciosamente falla, es muy recomendable buscar avisos. 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 redireccionamiento, a menudo deberías usar un lenguaje como este 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 fallas en el header()
.
Salida de búfer como solución alternativa
El búfer de salida de PHP es una solución para aliviar este problema. A menudo funciona de manera confiable, pero no debe sustituir la estructura adecuada de la aplicación y separar la salida de la lógica de control. Su propósito real es minimizar las transferencias fragmentadas al servidor web.
output_buffering=
embargo, el ajusteoutput_buffering=
puede ayudar. Configúrelo en el php.ini o vía .htaccess o incluso .user.ini en las configuraciones modernas de FPM / FastCGI.
Habilitarlo permitirá que PHP almacene en búfer la salida en lugar de pasarla al servidor web al instante. PHP así puede agregar encabezados HTTP.Igualmente, se puede activar con una llamada a
ob_start();
encima de la secuencia de comandos de invocación. Lo que sin embargo es menos confiable por múltiples razones:Incluso si
<?php ob_start(); ?>
<?php ob_start(); ?>
inicia el primer script, el espacio en blanco o una lista de materiales pueden ser barajados antes, haciéndolo inefectivo .Puede ocultar espacios en blanco para la salida HTML. Pero tan pronto como la lógica de la aplicación intenta enviar contenido binario (una imagen generada, por ejemplo), la salida extraña en búfer se convierte en un problema. (Necesidad de
ob_clean()
como solución alternativa).El tamaño del búfer es limitado, y se puede rebasar fácilmente cuando se deja por defecto. Y eso tampoco es una ocurrencia rara, difícil de rastrear cuando sucede.
Por lo tanto, ambos enfoques pueden volverse poco confiables, en particular al cambiar entre configuraciones de desarrollo y / o servidores de producción. Esta es la razón por la que el búfer de salida se considera ampliamente como una muleta / estrictamente una solución alternativa.
Vea también el ejemplo de uso básico en el manual, y para más ventajas y desventajas:
- ¿Qué es el búfer de salida?
- ¿Por qué usar el búfer de salida en PHP?
- ¿El uso del buffer de salida es una mala práctica?
- Caso de uso para el búfer de salida como la solución correcta para "encabezados ya enviados"
¿Pero funcionó en el otro servidor?
Si no recibió la advertencia de encabezados anteriormente, entonces la output_buffering= ha cambiado. Es probable que esté desconfigurado en el servidor actual / nuevo.
Comprobando con headers_sent()
Siempre puede usar headers_sent()
para sondear si aún es posible ... enviar encabezados. Lo que es útil para imprimir condicionalmente una información o aplicar otra lógica de reserva.
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
Las soluciones alternativas útiles son:
Etiqueta
<meta>
HTMLSi su aplicación es estructuralmente difícil de arreglar, entonces una forma fácil (pero poco profesional) de permitir redirecciones es inyectar una etiqueta HTML
<meta>
. Una redirección se puede lograr con:<meta http-equiv="Location" content="http://example.com/">
O con un breve retraso:
<meta http-equiv="Refresh" content="2; url=../target.html">
Esto lleva a un HTML no válido cuando se utiliza más allá de la sección
<head>
. La mayoría de los navegadores todavía lo aceptan.Redireccionamiento de JavaScript
Como alternativa, se puede utilizar una redirección de JavaScript para las redirecciones de página:
<script> location.replace("target.html"); </script>
Si bien esto suele ser más compatible con HTML que la solución
<meta>
, incurre en la dependencia de clientes con capacidad para JavaScript.
Sin embargo, ambos enfoques hacen aceptables alternativas cuando fallan las llamadas al encabezado HTTP genuino (). Lo ideal sería que siempre combinara esto con un mensaje fácil de usar y un enlace seleccionable como último recurso. (Lo que, por ejemplo, es lo que hace la http_redirect() PECL).
Por qué setcookie()
y session_start()
también se ven afectados
Tanto setcookie()
como session_start()
necesitan enviar un encabezado Set-Cookie:
HTTP. Por lo tanto, se aplican las mismas condiciones, y se generarán mensajes de error similares para situaciones de salida prematura.
(Por supuesto, también están afectadas por las cookies deshabilitadas en el navegador, o incluso por problemas de proxy. La funcionalidad de la sesión, obviamente, también depende del espacio libre en el disco y otras configuraciones de php.ini, etc.)
Otros enlaces
- Google proporciona una larga lista de discusiones similares .
- Y, por supuesto, muchos casos específicos también se han cubierto en .
- Las preguntas frecuentes de Wordpress explican ¿Cómo resuelvo los problemas de advertencia de los encabezados que ya se enviaron? de manera genérica.
- Comunidad de Adobe: desarrollo de PHP: por qué las redirecciones no funcionan (encabezados ya enviados)
- Preguntas frecuentes sobre Nucleus: ¿Qué significa "encabezados de página ya enviados"?
- Una de las explicaciones más completas es Encabezados HTTP y la función de encabezado PHP () - Un tutorial de NicholasSolutions (enlace a Internet Archive). Cubre HTTP en detalle y da algunas pautas para reescribir scripts.
A veces, cuando el proceso dev tiene estaciones de trabajo WIN y sistemas LINUX (hosting) y en el código no ve ninguna salida antes de la línea relacionada, podría ser el formato del archivo y la falta de la línea de Unix LF (salto de línea ). .
Lo que normalmente hacemos para solucionar esto rápidamente es cambiar el nombre del archivo y, en el sistema LINUX, crear un nuevo archivo en lugar del nuevo, y luego copiar el contenido. Muchas veces esto resuelve el problema, ya que algunos de los archivos que se crearon en WIN una vez que se movieron al alojamiento causan este problema.
Esta solución es una solución fácil para los sitios que administramos mediante FTP y, en ocasiones, puede ahorrarle tiempo a los nuevos miembros de nuestro equipo.
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 va a resolver su problema. Me enfrenté al mismo problema, pero lo resolví escribiendo la ubicación del encabezado de la forma anterior.
Es por esta línea:
printf ("Hi %s,</br />", $name);
No debe imprimir / hacer eco de nada antes de enviar los encabezados.
Este mensaje de error se activa cuando se envía algo antes de enviar los encabezados HTTP (con setcookie() o header() ). Las razones comunes para generar algo antes de los encabezados HTTP son:
Espacio en blanco accidental, a menudo al principio o al final de los archivos, como este:
<?php // Note the space before "<?php" ?>
Para evitar esto, simplemente omita el cierre ?>
- No es obligatorio de todos modos.
- Marcas de orden de bytes al principio 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 BOMEF BB BF
desde el inicio de los archivos. - Salida explícita, como llamadas a
echo
,printf
,readfile
,readfile
, code before<?
etc. - Una advertencia emitida por php, si la propiedad
display_errors
php.ini está establecida. En lugar de estrellarse en un error de programación, php corrige el error en silencio y emite una advertencia. Si bien puede modificar las configuraciones error_reporting o error_reporting , debería solucionar el problema.
Las razones comunes son los accesos a elementos no definidos de una matriz (como$_POST[''input'']
sin usarempty
o isset() para probar si la entrada está establecida), o usar una constante indefinida en lugar de un literal de cadena (como en$_POST[input]
, tenga en cuenta las citas que faltan).
Activar el búfer 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 intermedia hasta que libera el búfer, por ejemplo, con ob_end_flush
.
Sin embargo, aunque el búfer de salida evita los problemas, realmente debe determinar por qué su aplicación genera un cuerpo HTTP antes del encabezado HTTP. Eso sería como tomar una llamada telefónica y hablar sobre su día y el clima antes de decirle a la persona que llama que tiene el número equivocado.
Generalmente este error surge cuando enviamos encabezado después de hacer eco o imprimir. Si este error surge en una página específica, asegúrese de que la página no tenga ningún eco antes de llamar a start_session()
.
Ejemplo de error impredecible:
<?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();
//your page content
Un ejemplo más:
<?php
includes ''functions.php'';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();
//your page content
Conclusión: no genere ningún carácter antes de llamar a session_start()
o header()
funciones ni siquiera un espacio en blanco o una nueva línea
Otra mala práctica puede invocar este problema que aún no se ha indicado.
Ver este fragmento de código:
<?php
include(''a_important_file.php''); //really really really bad practise
header("Location:A location");
?>
Las cosas están bien, ¿verdad?
¿Qué pasa si "a_important_file.php" es esto:
<?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-------------------
¿Esto no funcionará? Porque ya se genera una nueva línea.
Ahora, aunque este no es un escenario común, ¿qué sucede si está utilizando un marco MVC que carga muchos archivos antes de entregar las cosas a su controlador? Este no es un escenario poco común. Prepárate para esto.
Desde PSR-2 2.2:
- Todos los archivos PHP DEBEN utilizar el
Unix LF (linefeed) line ending
. - Todos los archivos PHP DEBEN terminar con una
single blank line
. - La etiqueta de cierre?> DEBE
omitted
de los archivos que contienenonly php
Créeme, seguir estas normas puede ahorrarle muchísimas horas de su vida :)
Recibí 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 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. Verifique 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 al guardar el archivo guardado. Esto no debería suceder. Si está utilizando Linux. puede usar el editor VI para eliminar espacios / líneas después de?> al final de la página.
Si este no es su caso, entonces puede usar ob_start para el búfer de salida como se muestra a continuación:
Posible solución 2:
<?php
ob_start();
// code
ob_end_flush();
?>
Esto activará el búfer de salida y sus encabezados se crearán después de que la página esté en búfer.
Tú lo haces
printf ("Hi %s,</br />", $name);
Antes de configurar las cookies, lo que no está permitido. No puede enviar ninguna salida antes de los encabezados, ni siquiera una línea en blanco.
Un consejo simple: ¡Un espacio simple (o carácter especial invisible) en su script, justo antes de la primera etiqueta <?php
, puede causar esto! Especialmente cuando estás trabajando en un equipo y alguien está utilizando un IDE "débil" o se ha metido en los archivos con editores de texto extraño.
He visto estas cosas;)