Hoy hablaremos sobre el problema de encabezados y sesiones con PHP para solucionar el error Headers already sent.
Si quieres solucionar el error Cannot modify header information – headers already sent y Warning: session_start(): Session cannot be started after headers have already been sent in en PHP, entonces verifica que:
echo
, printf
, HTML) antes de invocar a session_start
, setcookie
, header
y similares en tu propio script ni en los que hayas incluido con include
, require
, etcétera. Las funciones que modifican los encabezados deben ser invocadas antes de enviar un byte de información al cliente<?php
o un bloque de HTML intercalado antes de invocar a session_start
, header
, setcookie
, etcétera.Solo como una solución alterna, también puedes activar y aumentar el tamaño del búfer de salida editando el archivo php.ini. En algunos casos su valor es Off
pero puedes cambiarlo a output_buffering=4096
en donde 4096 es el tamaño en bytes, mismo que puede ser aumentado según tus necesidades.
Existen más posibles soluciones y causas, te invito a leer el artículo completo para revisar la raíz de este problema.
Los encabezados HTTP no pueden ser enviados después de la salida; es obligatorio que sean enviados antes del cuerpo de respuesta. Por lo tanto, lo siguiente es incorrecto:
<?php
echo json_encode([1, 2, 3]);
header("Content-Type: application/json");
Lo correcto sería:
<?php
header("Content-Type: application/json");
echo json_encode([1, 2, 3]);
En la mayoría de casos, las sesiones y cookies van a enviar encabezados, así que las llamadas a setcookie
, session_start
y similares deben ser realizadas antes que cualquier otra cosa.
Por lo tanto, lo siguiente es incorrecto:
<p>Hola mundo</p>
<?php
echo json_encode([1, 2, 3]);
session_start();
Ya que todas las funciones que modifiquen o envíen encabezados deben ser invocadas antes de cualquier otra salida. Puedes hacer include o require de un archivo siempre y cuando no imprima nada ya sea con echo
, printf
o con bloques de código HTML.
Sorprendentemente (pero totalmente documentado), en algunos casos, los ejemplos previamente mostrados como incorrectos van a funcionar en algunos entornos, y todo es debido a la configuración del búfer de salida.
No te confíes, ya que una cosa es el modo local y otra cosa el modo producción. Es mejor conocer sobre el búfer de salida para prevenir el error headers already sent.
La directiva output_buffering
importa mucho al obtener el error headers already sent y Session cannot be started after headers have already been sent en PHP.
Básicamente el búfer de salida almacena todo lo que se va a enviar en la respuesta HTTP sin imprimirlo, y al terminar el script envía primero los encabezados y después todo lo almacenado en el búfer, sin importar el orden en el que cada cosa fue enviada.
Si tenemos un búfer lo suficientemente grande, entonces podemos enviar los encabezados en cualquier momento y no habrá ningún error.
El problema ocurre cuando la salida es más grande que el búfer o el búfer está desactivado. Veamos algunos ejemplos… ¿recuerdas el ejemplo previamente mostrado como incorrecto?
<?php
echo json_encode([1, 2, 3]);
header("Content-Type: application/json");
Si yo lo ejecuto localmente en mi entorno (que tiene output_buffering=4096
) no ocurre ningún error y el encabezado es enviado correctamente. Primero se envía el header
y después el echo
, aunque el orden de llamada haya sido exactamente en el orden opuesto.
Pero si yo envío una salida más grande que el valor de output_buffering
con el siguiente código que imprime al menos 5000 caracteres:
<?php
echo json_encode(str_repeat("1", 5000));
header("Content-Type: application/json");
Entonces me aparece el error: Warning: Cannot modify header information – headers already sent by (output started at archivo:línea) in archivo.php on line 3
Así que dependiendo del tamaño del búfer y de la salida este error puede aparecer solo en algunos casos.
Suponiendo que la directiva está configurada en output_buffering=Off
, es decir, que el búfer de salida está desactivado (lo cual es el ajuste por defecto en varios servicios de alojamiento), entonces el ejemplo incorrecto y corto que funcionaba previamente:
<?php
echo json_encode([1, 2, 3]);
header("Content-Type: application/json");
Ya no va a funcionar. Al probarlo con esa configuración, el error será: Warning: Cannot modify header information – headers already sent by (output started at C:\xampp\htdocs\headers-already-sent\manual.php:2) in C:\xampp\htdocs\headers-already-sent\manual.php on line 3
Pasará lo mismo al iniciar una sesión:
Warning: session_start(): Session cannot be started after headers have already been sent in C:\xampp\htdocs\headers-already-sent\manual.php on line 3
Pero se va a solucionar arreglando el código para que primero se envíen todos los encabezados y después cualquier otra salida:
<?php
session_start();
echo json_encode([1, 2, 3]);
Algunas versiones del Bloc de notas dejan el BOM o Byte Order Mark al editar un archivo. Este BOM no se imprime (digamos que es invisible) pero causa que la salida sea enviada.
Puede que te estés preguntando quién se atrevería a editar un archivo de PHP con el Bloc de notas de Windows, y aunque es poco probable, cuando uno está en la computadora local del cliente con Windows y hay que hacer una edición de último momento, el único editor instalado por defecto es el bloc de notas.
El bloc de notas puede ser solo una de tantas razones para que el archivo tenga el BOM. He desarrollado una herramienta que detecta si tu archivo tiene el BOM para que puedas removerlo.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.