Découvrez "Headers already sent" : votre nouvel ennemi (et ami)
\n\nSi vous avez déjà codé en PHP, vous avez forcément croisé cette erreur. Elle surgit soudainement, souvent au pire moment — quand vous pensiez avoir terminé votre script. Le message est rouge, effrayant, et donne l'impression que tout votre code est cassé. Pourtant, c'est l'une des erreurs les plus utiles en PHP. Elle vous apprend à travailler correctement avec le protocole HTTP.
\n\nDans ce tutoriel, nous allons voir pourquoi l'erreur Headers already sent se produit, comment la diagnostiquer et, surtout, comment la corriger définitivement. Pas de simple copier-coller depuis Stack Overflow — nous allons comprendre le fond du problème. C'est parti !
Que sont les en-têtes HTTP et pourquoi PHP les protège-t-il ?
\n\nAvant de traiter le problème, il faut comprendre l'anatomie d'une réponse HTTP. Quand PHP envoie une réponse au navigateur, il le fait en deux étapes :
\n\n- \n
- D'abord, les en-têtes (headers). Ce sont les informations de service : type de contenu (
Content-Type), encodage, cookies, statut de la réponse (200 OK, 404 Not Found). \n - Ensuite, le corps de la réponse (body). C'est le HTML, le texte, le JSON — ce que l'utilisateur voit. \n
Le problème, c'est que PHP ne peut pas envoyer d'en-têtes après avoir commencé à envoyer le corps. Si vous essayez d'appeler header() après avoir affiché ne serait-ce qu'un seul caractère (même un espace), PHP génère une erreur :
Warning: Cannot modify header information - headers already sent by (output started at /path/to/file.php:12)\n\nVoilà tout le mystère. L'erreur n'est pas fatale — c'est un avertissement que votre header() n'a pas fonctionné. Mais les conséquences peuvent être graves : une redirection ne s'effectuera pas, un cookie ne sera pas défini, une réponse JSON sera corrompue.
\n\nTop 5 des causes de cette erreur
\n\nPassons en revue les scénarios les plus fréquents. Vous reconnaissez-vous ?
\n\n1. Espace ou ligne vide avant <?php
\n\nC'est un classique. Vous ouvrez un fichier, et avant la balise ouvrante <?php, il y a un espace, une ligne vide ou un caractère BOM (Byte Order Mark). PHP interprète ce caractère comme une sortie — et le problème commence.
// ❌ Erreur : espace avant <?php\n <?php\nheader('Location: /new-page.php');\n?>\n\n// ✅ Correct : aucun caractère avant <?php\n<?php\nheader('Location: /new-page.php');\n?>\n\n2. Affichage via echo ou print avant header()
\n\nUne erreur logique mais fréquente chez les débutants : afficher quelque chose, puis essayer de rediriger l'utilisateur.
\n\n<?php\necho "Bonjour tout le monde !";\nheader('Location: /merci.php'); // ❌ Erreur : sortie déjà envoyée\n?>\n\n3. Code HTML avant le bloc PHP
\n\nLe fichier peut contenir du code mixte : d'abord du HTML, puis de la logique PHP avec header().
\n\n<!DOCTYPE html>\n<html>\n<head>\n <title>Mon site</title>\n</head>\n<body>\n<?php\nheader('Location: /connexion.php'); // ❌ Erreur : HTML déjà envoyé\n?>\n</body>\n</html>\n\n4. Erreurs PHP et fonctions comme var_dump()
\n\nLe script peut afficher des avertissements ou des informations de débogage avant l'appel à header(). Par exemple, si display_errors est activé et que PHP affiche un warning.
<?php\nvar_dump($une_variable); // Affichage de données\nheader('Content-Type: application/json'); // ❌ Erreur\n?>\n\n5. Caractères invisibles dans les fichiers inclus (include/require)
\n\nVous incluez un fichier avec include ou require, et à la fin de ce fichier, il y a une ligne vide ou un espace après la balise fermante ?>.
// config.php\n<?php\n$db_host = 'localhost';\n?>\n // ← Cet espace après ?> casse tout !\n\nComment trouver la source du problème : diagnostic pas à pas
\n\nLe plus important : l'erreur indique toujours où la sortie a commencé. Lisez attentivement le message.