funciona - redirect php




Cómo corregir el error de "Encabezados ya enviados" en PHP (8)

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;

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?


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:

  • 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:

  1. Imprimir, echo

    La salida intencional de print declaraciones de print y echo 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 al header() 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.

  2. Á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 de header() 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.

  3. 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.

  4. 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.

  5. ¿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 menudo include()d scripts son los culpables.)

  6. 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 el ob_gzhandler .
    • Pero también podría ser cualquier extension= módulo cargado doblemente que genere un mensaje de advertencia / inicio de PHP implícito.

  7. 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.

  1. output_buffering= embargo, el ajuste output_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.

  2. 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:

¿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> HTML

    Si 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


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.


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 contienen only php

Créeme, seguir estas normas puede ahorrarle muchísimas horas de su vida :)


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;)





header