Función PHP headers_sent(): Todo lo que necesitas saber
Como desarrollador PHP, puedes necesitar comprobar si las cabeceras HTTP ya se han enviado al cliente. La función headers_sent() es una función integrada de PHP
Toda respuesta HTTP se divide en dos partes: un bloque de cabeceras (código de estado, Content-Type, cookies, redirecciones) seguido del cuerpo de la respuesta. El problema es que las cabeceras deben enviarse antes de cualquier salida del cuerpo. En el momento en que PHP imprime un solo byte del cuerpo, envía las cabeceras y las bloquea — cualquier llamada posterior a header(), setcookie() o session_start() desencadena el famoso aviso Cannot modify header information - headers already sent.
headers_sent() es la función integrada que te permite preguntar, antes de intentar enviar una cabecera, si ya es demasiado tarde. Esta guía cubre su sintaxis, sus parámetros por referencia, qué causa la salida prematura y cómo solucionarlo.
Qué hace headers_sent()
headers_sent() devuelve un valor boolean:
true— las cabeceras ya se han enviado (la salida ha comenzado). Cualquier llamada posterior aheader()/setcookie()fallará.false— aún no ha comenzado ninguna salida, por lo que todavía es seguro establecer cabeceras.
Proteger la lógica de cabeceras con headers_sent() permite evitar el aviso y degradar con elegancia (por ejemplo, registrar el problema o recurrir a una redirección JavaScript) en lugar de romper la página.
Sintaxis
headers_sent(string &$filename = null, int &$line = null): boolAmbos parámetros son opcionales y se pasan por referencia. Cuando las cabeceras ya se han enviado, PHP los rellena con la ubicación de la salida que lo inició:
$filename— el nombre del archivo fuente donde comenzó la salida.$line— el número de línea dentro de ese archivo.
Esto es lo que hace que headers_sent() sea tan útil para depurar: te señala directamente al culpable.
Uso básico
Comprueba el valor de retorno antes de enviar una cabecera:
<?php
if (!headers_sent()) {
header('Location: /dashboard');
exit;
}
echo 'Headers were already sent, cannot redirect via HTTP.';Si la salida no ha comenzado, se envía la cabecera de redirección. De lo contrario, el script evita el aviso fatal e imprime un mensaje alternativo.
Encontrar dónde comenzó la salida
Pasa las dos variables por referencia para saber exactamente qué envió las cabeceras — invaluable cuando un espacio suelto o un echo está enterrado en un archivo incluido:
<?php
if (headers_sent($file, $line)) {
echo "Headers already sent in $file on line $line";
} else {
setcookie('theme', 'dark');
echo 'Cookie set successfully.';
}Si la condición es verdadera, obtienes un mensaje como Headers already sent in /var/www/header.php on line 12, indicándote exactamente dónde buscar.
Qué desencadena "Headers Already Sent"
Cualquier cosa que produzca salida del cuerpo antes de tu llamada a la cabecera envía las cabeceras. Causas comunes:
- Espacios en blanco o una línea en blanco antes de
<?php— incluso un espacio o salto de línea cuenta como salida. - Un salto de línea después del
?>de cierre de un archivo incluido. (Buena práctica: omite el?>de cierre en archivos puramente PHP.) echo,print,printfovar_dumpejecutados antes de la cabecera.- Un archivo UTF-8 guardado con BOM (marca de orden de bytes) — esos bytes iniciales invisibles son salida.
- Avisos/notificaciones de PHP impresos en la página (cuando
display_errorsestá activado) antes de las cabeceras.
Solución con almacenamiento en búfer de salida
Si no puedes reordenar tu código para que todas las cabeceras vengan primero, envuelve el script en un búfer de salida. ob_start() mantiene el cuerpo en memoria en lugar de enviarlo inmediatamente, por lo que las cabeceras permanecen modificables hasta que se vacía el búfer:
<?php
ob_start(); // start buffering — nothing is sent yet
echo 'Some early output';
// Still safe: the echo above is held in the buffer, headers are not sent
setcookie('user', 'jane');
header('X-App-Version: 2.0');
ob_end_flush(); // now send headers, then the buffered bodyDado que la salida está en búfer, headers_sent() aún devolvería false después del echo, y las llamadas posteriores a setcookie() y header() se ejecutan correctamente.
Funciones relacionadas
header()— envía una cabecera HTTP sin procesar.headers_list()— lista las cabeceras en cola o ya enviadas.setcookie()— establece una cookie (envía una cabeceraSet-Cookie).ob_start()— inicia el almacenamiento en búfer de salida para retrasar el envío de cabeceras.- Sesiones PHP —
session_start()también envía cabeceras y es un desencadenante frecuente.
Conclusión
headers_sent() es un guardián pequeño pero esencial: llámalo antes de cualquier header(), setcookie() o session_start() para comprobar si la salida ya ha comenzado. Cuando devuelve true, los argumentos por referencia $filename y $line identifican con precisión la salida problemática para que puedas corregirla — o envuelve tu script en ob_start() para mantener las cabeceras modificables hasta que estés listo para vaciar el búfer.