831 votes

Comment corriger l'erreur "Headers already sent" en PHP ?

Lorsque j'exécute mon script, j'obtiens plusieurs erreurs comme celle-ci :

Avertissement : Impossible de modifier les informations d'en-tête - les en-têtes ont déjà été envoyés par ( la sortie a commencé à /some/file.php:12 ) en /some/file.php sur ligne 23

Les lignes mentionnées dans les messages d'erreur contiennent header() y setcookie() appels.

Quelle pourrait en être la raison ? Et comment y remédier ?

0 votes

0 votes

Assurez-vous qu'aucun texte n'est édité ( ob_start y ob_end_clean() peut s'avérer utile ici). Vous pourriez alors définir un cookie ou une session égale à ob_get_contents() et ensuite utiliser ob_end_clean() pour vider le tampon.

0 votes

Utilisez le safeRedirect dans ma bibliothèque PHP : github.com/heinkasner/PHP-Library/blob/master/extra.php

3162voto

mario Points 76989

Pas de sortie avant l'envoi des en-têtes !

Les fonctions qui envoient/modifient les en-têtes HTTP doivent être invoquées. avant toute sortie . <a href="https://stackoverflow.com/a/8028979/345031"><strong>summary </strong></a> Sinon, l'appel échoue :

Avertissement : Cannot modify header information - headers already sent (output started at script:ligne )

Certaines fonctions modifiant l'en-tête HTTP sont :

La sortie peut être :

  • Non intentionnel :

  • Intentionnel :

    • print , echo et d'autres fonctions produisant des résultats
    • Brut <html> sections précédentes <?php code.

Pourquoi cela se produit-il ?

Pour comprendre pourquoi les en-têtes doivent être envoyés avant la sortie, il faut d'examiner un exemple typique HTTP réponse. Les scripts PHP génèrent principalement du contenu HTML, mais passent également un ensemble d'en-têtes HTTP/CGI au serveur web :

HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8

<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="http://stackoverflow.com/"> <img src=internal-icon-delayed> </a>

La page/la sortie est toujours suit les en-têtes. PHP doit d'abord passer les les en-têtes au serveur web d'abord. Il ne peut le faire qu'une seule fois. Après le double saut de ligne, il ne peut plus jamais les modifier.

Lorsque PHP reçoit la première sortie ( print , echo , <html> ), elle affleurant tous les en-têtes collectés. Ensuite, il peut envoyer tout ce qu'il veut qu'il veut. Mais l'envoi d'autres en-têtes HTTP est alors impossible.

Comment pouvez-vous savoir où la sortie prématurée s'est produite ?

El header() L'avertissement contient toutes les informations pertinentes pour localiser la cause du problème :

Avertissement : Impossible de modifier les informations d'en-tête - en-têtes déjà envoyés par (la sortie a commencé à /www/usr2345/htdocs/ auth.php:52 ) dans /www/usr2345/htdocs/index.php sur la ligne 100

Ici, la "ligne 100" se réfère au script où la header() invocation échoué.

Le " La sortie a commencé à La note " entre parenthèses " est plus significative. Elle dénomme la source de la sortie précédente. Dans cet exemple, c'est auth.php et ligne 52 . C'est là qu'il fallait chercher une sortie prématurée.

Causes typiques :

  1. Impression, écho

    Sortie intentionnelle de print y echo mettront fin à la possibilité d'envoyer des en-têtes HTTP. Le flux de l'application doit être restructuré pour éviter cela. Utilisez fonctions et des schémas de modélisation. Assurez-vous que header() des appels ont lieu avant Les messages sont écrits.

    Les fonctions qui produisent des résultats comprennent

    • print , echo , printf , vprintf
    • trigger_error , ob_flush , ob_end_flush , var_dump , print_r
    • readfile , passthru , flush , imagepng , imagejpeg

    entre autres, et des fonctions définies par l'utilisateur.

  2. Zones HTML brutes

    Les sections HTML non analysées dans un .php sont également des sorties directes. script conditions qui déclencheront une header() l'appel doit être noté avant tout brut <html> blocs.

    <!DOCTYPE html>
    <?php
        // Too late for headers already.

    Utilisez un schéma de modélisation pour séparer le traitement de la logique de sortie.

    • Placez le code de traitement du formulaire au sommet des scripts.
    • Utilisez des variables temporaires de type chaîne pour différer les messages.
    • La logique de sortie réelle et la sortie HTML mélangée devraient suivre en dernier.
  3. Espace blanc avant <?php pour "script.php ligne 1 "Avertissements

    Si l'avertissement fait référence à une sortie en ligne 1 alors c'est surtout leader espace blanc , du texte ou du HTML avant l'ouverture <?php jeton.

     <?php
    # There's a SINGLE space/newline before <? - Which already seals it.

    De même, cela peut se produire pour les sections scripts ou scripts annexées :

    ?>
    
    <?php

    PHP consomme en fait un simple rupture de ligne après les balises fermées. Mais il ne pourra pas compensera pas les multiples sauts de ligne, tabulations ou espaces décalés dans ces espaces.

  4. NOMENCLATURE UTF-8

    Les ruptures de ligne et les espaces seuls peuvent être un problème. Mais il existe aussi des séquences de caractères "invisibles" qui peuvent causer ce problème. Le plus connu est le NOMENCLATURE UTF-8 (marque d'ordre d'octet) qui n'est pas affiché par la plupart des éditeurs de texte. Il s'agit de la séquence d'octets EF BB BF qui est facultatif et redondant pour les documents codés en UTF-8. PHP doit cependant le traiter comme une sortie brute. Il peut apparaître sous la forme des caractères dans la sortie (si le client interprète le document en Latin-1) ou d'autres "déchets" similaires.

    En particulier, les éditeurs graphiques et les IDE basés sur Java sont inconscients de son présence. Ils ne le visualisent pas (obligés par la norme Unicode). La plupart des éditeurs de programmeurs et de consoles le font cependant :

    joes editor showing UTF-8 BOM placeholder, and MC editor a dot

    Là, il est facile de reconnaître le problème dès le début. D'autres éditeurs peuvent identifier sa présence dans un menu de fichiers/paramètres (Notepad++ sous Windows peut identifier et corriger le problème). remédier au problème ), Une autre option pour inspecter la présence des nomenclatures est de recourir à un outil de contrôle de la qualité. éditeur hexagonal . Sur les systèmes *nix hexdump est généralement disponible, si ce n'est une variante graphique qui simplifie l'audit de ces questions et d'autres :

    beav hexeditor showing utf-8 bom

    Une solution simple consiste à configurer l'éditeur de texte pour qu'il enregistre les fichiers en "UTF-8 (sans BOM)". ou une nomenclature similaire. Les nouveaux venus ont souvent recours à la création de nouveaux fichiers et au copier-coller du code précédent.

    Utilitaires de correction

    Il existe également des outils automatisés permettant d'examiner et de réécrire des fichiers texte ( sed / awk o recode ). Pour PHP en particulier, il existe l'option phptags étiquette plus propre . Il réécrit les balises close et open en formes longue et courte, mais aussi facilement corrige facilement les problèmes d'espacement en fin de ligne, d'Unicode et de BOM UTF-x :

    phptags  --whitespace  *.php

    Il peut être utilisé en toute sécurité sur un répertoire entier d'inclusion ou de projet.

  5. Espace blanc après ?>

    Si la source de l'erreur est mentionnée comme étant derrière le fermeture du site ?> alors c'est là que certains espaces ou le texte brut ont été écrits. Le marqueur de fin PHP ne met pas fin à l'exécution du script à ce stade. Tout texte/espace après lui sera écrit comme contenu de page encore.

    Il est généralement conseillé, en particulier aux nouveaux arrivants, que le trailing ?> PHP les balises de fermeture doivent être omises. Ce site évite le site une petite partie de ces cas. (Assez couramment include()d scripts sont les coupables).

  6. La source de l'erreur est mentionnée comme "Inconnu sur la ligne 0".

    C'est typiquement une extension PHP ou un paramètre du php.ini si aucune source d'erreur n'est concrétisée.

    • C'est parfois le gzip réglage du codage du flux ou le ob_gzhandler .
    • Mais il peut aussi s'agir de n'importe quelle charge double extension= module générant un message implicite de démarrage/alerte de PHP.
  7. Messages d'erreur précédents

    Si une autre déclaration ou expression PHP provoque un message d'avertissement ou une erreur de la part de l'utilisateur. est imprimé, cela compte aussi comme une sortie prématurée.

    Dans ce cas, vous devez éviter l'erreur, retarder l'exécution de l'instruction, ou supprimer le message en utilisant, par exemple, la fonction isset() o @() - quand l'un ou l'autre n'entrave pas le débogage ultérieur.

Aucun message d'erreur

Si vous avez error_reporting o display_errors handicap par php.ini , alors aucun avertissement n'apparaîtra. Mais ignorer les erreurs ne fera pas disparaître le problème. problème. Les en-têtes ne peuvent toujours pas être envoyés après une sortie prématurée.

Alors quand header("Location: ...") redirections échouent silencieusement, c'est très conseillé de vérifier les avertissements. Réactivez-les avec deux commandes simples au sommet de l'invocation script :

error_reporting(E_ALL);
ini_set("display_errors", 1);

Ou set_error_handler("var_dump"); si tout le reste échoue.

En parlant d'en-têtes de redirection, vous devriez souvent utiliser une idiome comme ceci pour les chemins de code finaux :

exit(header("Location: /finished.html"));

De préférence même une fonction utilitaire, qui imprime un message utilisateur en cas de header() échecs.

Mise en mémoire tampon de la sortie comme solution de rechange

PHPs mise en mémoire tampon des sorties est une solution de contournement pour pallier à ce problème. Elle fonctionne souvent de manière fiable, mais ne doit pas se substituer à une structuration correcte de l'application et à la séparation de la sortie et de la de contrôle. Son but réel est de minimiser les transferts de données en morceaux vers le serveur web.

  1. El output_buffering= Le réglage peut néanmoins aider. Configurez-le dans le php.ini ou via .htaccess ou même .user.ini sur les configurations modernes de FPM/FastCGI.
    L'activer permet à PHP de mettre en mémoire tampon la sortie au lieu de la transmettre instantanément au serveur web. PHP peut ainsi agréger les en-têtes HTTP.

  2. Il peut également être engagé avec un appel à ob_start(); au sommet de l'invocation script. Ce qui est cependant moins fiable pour de multiples raisons :

    • Même si <?php ob_start(); ?> commence le premier script, un espace blanc ou un BOM peuvent être mélangés avant, le rendant inefficace .

    • Il peut dissimuler les espaces blancs pour la sortie HTML. Mais dès que la logique applicative tente d'envoyer un contenu binaire (une image générée par exemple), la sortie étrangère mise en mémoire tampon devient un problème. (Nécessité de ob_clean() comme solution de rechange supplémentaire).

    • La taille de la mémoire tampon est limitée et peut facilement déborder si elle est laissée à ses valeurs par défaut. Et ce n'est pas un cas rare non plus, difficile à trouver quand ça arrive.

Les deux approches peuvent donc devenir peu fiables, notamment lorsqu'on passe d'un mode à l'autre. les configurations de développement et/ou les serveurs de production. C'est pourquoi la mise en tampon de la sortie est largement considéré comme une simple béquille / une solution de contournement.

Voir aussi le exemple d'utilisation de base dans le manuel, et pour d'autres avantages et inconvénients :

Mais ça a marché sur l'autre serveur ! ?

Si vous n'avez pas reçu l'avertissement sur les en-têtes avant, alors l'option mise en mémoire tampon de la sortie Paramètres du php.ini a changé. Il est probablement non configuré sur le serveur actuel/nouveau.

Vérification avec headers_sent()

Vous pouvez toujours utiliser headers_sent() pour vérifier si il est encore possible... d'envoyer des en-têtes. Ce qui est utile pour imprimer conditionnellement des informations ou appliquer une autre logique de repli.

if (headers_sent()) {
    die("Redirect failed. Please click on this link: <a href=...>");
}
else{
    exit(header("Location: /user.php"));
}

Les solutions de rechange utiles sont les suivantes :

  • HTML <meta> étiquette

    Si votre application est structurellement difficile à réparer, alors une solution facile (mais peu professionnelle) pour autoriser les redirections est d'injecter un fichier HTML <meta> tag. Une redirection peut être réalisée avec :

     <meta http-equiv="Location" content="http://example.com/">

    Ou avec un court délai :

     <meta http-equiv="Refresh" content="2; url=../target.html">

    Cela conduit à des HTML non valides lorsqu'ils sont utilisés au-delà de la date limite de réception. <head> section. La plupart des navigateurs l'acceptent encore.

  • Redirection JavaScript

    Comme alternative a Redirection JavaScript peut être utilisé pour les redirections de pages :

     <script> location.replace("target.html"); </script>

    Bien que cette méthode soit souvent plus conforme au HTML que l'option <meta> solution de contournement, elle implique une dépendance à l'égard des clients compatibles avec JavaScript.

Les deux approches constituent cependant des solutions de repli acceptables lorsque les appels HTTP header() authentiques échouent. Idéalement, vous devriez toujours combiner cette approche avec un message convivial et un lien cliquable en dernier recours. un lien cliquable en dernier recours. (Ce qui, par exemple, est ce que le http_redirect() L'extension PECL le fait).

Pourquoi setcookie() y session_start() sont également concernés

Les deux sites setcookie() y session_start() doivent envoyer un Set-Cookie: En-tête HTTP. Les mêmes conditions s'appliquent donc, et des messages d'erreur similaires seront générés pour les situations de sortie prématurée.

(Bien entendu, ils sont en outre affectés par les cookies désactivés dans le navigateur. ou même des problèmes de proxy. La fonctionnalité de session dépend évidemment aussi de l'espace l'espace disque disponible et d'autres paramètres du php.ini, etc.)

Autres liens

0 votes

L'utilisation de notepad.exe est également délicate. J'utilise normalement NetBeans qui n'ajoute pas de BOM, même si le fichier est encodé ainsi. L'édition d'un fichier plus tard dans le bloc-notes perturbe les choses, surtout avec IIS comme serveur web. Il semble qu'Apache rejette la nomenclature (ajoutée intentionnellement).

4 votes

Retrait de la fermeture ?> de la fin d'un fichier php est généralement une bonne pratique qui aide à minimiser ces erreurs également. Les espaces non désirés ne se produiront pas à la fin des fichiers, et vous pourrez toujours ajouter des en-têtes à la réponse plus tard. C'est également pratique si vous utilisez la mise en mémoire tampon de sortie et que vous ne souhaitez pas voir d'espaces blancs non désirés à la fin des parties générées par les fichiers inclus.

0 votes

Chose étrange, j'ai déplacé mon fichier de l'hébergement Linux de cPanel à VPS. Avant, il fonctionnait correctement, mais ici, il a montré cette erreur (j'avais du code html avant l'en-tête). Pourquoi ?

205voto

phihag Points 89765

Ce message d'erreur se déclenche lorsque tout ce qui est est envoyé avant que vous n'envoyiez les en-têtes HTTP (avec setcookie o header ). Les raisons courantes pour lesquelles il faut afficher quelque chose avant les en-têtes HTTP sont les suivantes :

  • Espace blanc accidentel, souvent au début ou à la fin des fichiers, comme ceci :

     <?php
    // Note the space before "<?php"
    ?>

       Pour éviter cela, il suffit d'omettre la fermeture ?> - ce n'est pas obligatoire de toute façon.

  • Marques de l'ordre des octets au début d'un fichier php. Examinez vos fichiers php avec un éditeur hexadécimal pour savoir si c'est le cas. Ils devraient commencer par les octets 3F 3C . Vous pouvez retirer la nomenclature en toute sécurité EF BB BF dès le début des dossiers.
  • Les sorties explicites, telles que les appels à echo , printf , readfile , passthru code avant <? etc.
  • Un avertissement affiché par php, si le display_errors La propriété php.ini est définie. Au lieu de se planter sur une erreur du programmeur, php corrige silencieusement l'erreur et émet un avertissement. Bien que vous puissiez modifier la propriété display_errors o Signalement des erreurs configurations, vous devriez plutôt régler le problème.
    Les raisons courantes sont les accès à des éléments non définis d'un tableau (tels que $_POST['input'] sans utiliser empty o isset pour tester si l'entrée est définie), ou l'utilisation d'une constante indéfinie au lieu d'une chaîne littérale (comme dans $_POST[input] (notez les guillemets manquants).

Mise en marche mise en mémoire tampon des sorties devrait faire disparaître le problème ; toute la sortie après l'appel à ob_start est mis en mémoire tampon jusqu'à ce que vous libériez le tampon, par exemple avec ob_end_flush .

Toutefois, si la mise en mémoire tampon de la sortie permet d'éviter ces problèmes, vous devriez vraiment déterminer pourquoi votre application produit un corps HTTP avant l'en-tête HTTP. Ce serait comme prendre un appel téléphonique et discuter de votre journée et du temps qu'il fait avant de dire à votre interlocuteur qu'il s'est trompé de numéro.

126voto

Manish Shrivastava Points 4380

J'ai eu cette erreur plusieurs fois auparavant, et je suis certain que tous les programmeurs PHP ont eu cette erreur au moins une fois auparavant.

Solution possible 1

Cette erreur a pu être causée par les espaces vides avant le début du fichier ou après Ces espaces vides ne doivent pas se trouver ici.

ex) IL NE DOIT PAS Y AVOIR D'ESPACES VIDES ICI

   echo "your code here";

?>
THERE SHOULD BE NO BLANK SPACES HERE

Vérifiez tous les fichiers associés au fichier qui cause cette erreur.

Note : Parfois, les éditeurs (IDE) comme gedit (un éditeur linux par défaut) ajoutent une ligne vide dans le fichier de sauvegarde. Cela ne devrait pas se produire. Si vous utilisez Linux, vous pouvez utiliser l'éditeur VI pour supprimer les espaces/lignes après ?> à la fin de la page.

Solution possible 2 : Si ce n'est pas votre cas, utilisez alors ob_start à la mise en mémoire tampon de la sortie :

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

Cela activera la mise en tampon de la sortie et vos en-têtes seront créés après la mise en tampon de la page.

20 votes

ob_start() ne fait que masquer le problème ; ne l'utilisez pas pour résoudre ce problème particulier.

0 votes

@Jack Si je n'utilise pas de ob_start() alors que dois-je faire pour résoudre ce problème : Headers already sent

0 votes

@Sajad si vous obtenez l'erreur spécifiquement à cause de l'éditeur que vous utilisez, vous devriez jouer avec les paramètres pour qu'il cesse de causer le problème, ou changer d'éditeur. Si vous obtenez l'erreur pour une autre raison, vous devriez lire les réponses à cette question (en particulier la réponse acceptée) pour déterminer quel est le problème et le résoudre.

96voto

Ipsita Rout Points 628

Au lieu de la ligne ci-dessous

//header("Location:".ADMIN_URL."/index.php");

écrire

echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");

ou

?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php

Ça va certainement résoudre votre problème. J'ai rencontré le même problème mais je l'ai résolu en écrivant l'emplacement de l'en-tête de la manière décrite ci-dessus.

42voto

Seth Carnegie Points 45196

Tu le fais.

printf ("Hi %s,</br />", $name);

avant d'installer les cookies, ce qui n'est pas autorisé. Vous ne pouvez pas envoyer de sortie avant les en-têtes, pas même une ligne blanche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X