W3docs

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 a header() / 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): bool

Ambos 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, printf o var_dump ejecutados 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_errors está 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 body

Dado 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 cabecera Set-Cookie).
  • ob_start() — inicia el almacenamiento en búfer de salida para retrasar el envío de cabeceras.
  • Sesiones PHPsession_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.

Práctica

Práctica
¿Qué puede causar el aviso 'headers already sent' en PHP?
¿Qué puede causar el aviso 'headers already sent' en PHP?
Was this page helpful?