Fonction PHP headers_sent() : Tout ce que vous devez savoir
En tant que développeur PHP, vous pouvez vérifier si les en-têtes HTTP ont déjà été envoyés au client. headers_sent() est une fonction intégrée en PHP.
Chaque réponse HTTP est divisée en deux parties : un bloc d'en-têtes (code de statut, Content-Type, cookies, redirections) suivi du corps de la réponse. Le problème est que les en-têtes doivent être envoyés avant tout contenu du corps. Dès que PHP envoie un seul octet de corps, il expédie les en-têtes et les verrouille — tout appel ultérieur à header(), setcookie(), ou session_start() déclenche alors le célèbre avertissement Cannot modify header information - headers already sent.
headers_sent() est la fonction intégrée qui vous permet de vérifier, avant d'essayer d'envoyer un en-tête, s'il est déjà trop tard. Ce guide couvre sa syntaxe, ses paramètres par référence, ce qui provoque une sortie prématurée et comment y remédier.
Ce que fait headers_sent()
headers_sent() retourne un booléen :
true— les en-têtes ont déjà été envoyés (la sortie a commencé). Tout appel ultérieur àheader()/setcookie()échouera.false— aucune sortie n'a encore commencé, il est donc encore possible de définir des en-têtes.
Protéger la logique des en-têtes avec headers_sent() vous permet d'éviter l'avertissement et de gérer l'échec gracieusement (par exemple, journaliser le problème ou utiliser une redirection JavaScript) au lieu de faire planter la page.
Syntaxe
headers_sent(string &$filename = null, int &$line = null): boolLes deux paramètres sont optionnels et passés par référence. Lorsque les en-têtes ont été envoyés, PHP les remplit avec l'emplacement de la sortie qui les a déclenchés :
$filename— le nom du fichier source où la sortie a commencé en premier.$line— le numéro de ligne dans ce fichier.
C'est ce qui rend headers_sent() si utile pour le débogage : elle vous pointe directement vers le coupable.
Utilisation de base
Vérifiez la valeur de retour avant d'envoyer un en-tête :
<?php
if (!headers_sent()) {
header('Location: /dashboard');
exit;
}
echo 'Headers were already sent, cannot redirect via HTTP.';Si aucune sortie n'a commencé, l'en-tête de redirection est envoyé. Sinon, le script évite l'avertissement fatal et affiche un message de repli.
Trouver où la sortie a commencé
Passez les deux variables de référence pour savoir exactement ce qui a envoyé les en-têtes — indispensable lorsqu'un espace parasite ou un echo est enfoui dans un fichier inclus :
<?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 condition est vraie, vous obtenez un message comme Headers already sent in /var/www/header.php on line 12, vous indiquant précisément où chercher.
Ce qui déclenche "Headers Already Sent"
Tout ce qui produit une sortie de corps avant votre appel d'en-tête expédie les en-têtes. Causes courantes :
- Un espace ou une ligne vide avant
<?php— même un seul espace ou retour à la ligne compte comme une sortie. - Un retour à la ligne après le
?>fermant d'un fichier inclus. (Bonne pratique : omettre entièrement le?>fermant dans les fichiers PHP purs.) echo,print,printf, ouvar_dumpexécutés avant l'en-tête.- Un fichier UTF-8 enregistré avec un BOM (byte-order mark) — ces octets invisibles en début de fichier constituent une sortie.
- Des avertissements/notices PHP affichés sur la page (lorsque
display_errorsest activé) avant les en-têtes.
Résoudre le problème avec la mise en tampon de sortie
Si vous ne pouvez pas réorganiser votre code pour que tous les en-têtes viennent en premier, encapsulez le script dans un tampon de sortie. ob_start() conserve le corps en mémoire au lieu de l'envoyer immédiatement, de sorte que les en-têtes restent modifiables jusqu'à ce que le tampon soit vidé :
<?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 bodyComme la sortie est mise en tampon, headers_sent() retournerait toujours false après le echo, et les appels ultérieurs à setcookie() et header() réussissent.
Fonctions associées
header()— envoyer un en-tête HTTP brut.headers_list()— lister les en-têtes en attente ou déjà envoyés.setcookie()— définir un cookie (envoie un en-têteSet-Cookie).ob_start()— démarrer la mise en tampon de sortie pour retarder l'envoi des en-têtes.- PHP Sessions —
session_start()envoie aussi des en-têtes et est un déclencheur fréquent.
Conclusion
headers_sent() est une petite garde mais essentielle : appelez-la avant tout header(), setcookie(), ou session_start() pour vérifier si une sortie a déjà commencé. Lorsqu'elle retourne true, les arguments par référence $filename et $line identifient précisément la sortie en cause pour que vous puissiez la corriger — ou encapsulez votre script dans ob_start() pour garder les en-têtes modifiables jusqu'à ce que vous soyez prêt à vider le tampon.