Lors de l'exécution de mon script, je reçois plusieurs erreurs comme ceci:
Avertissement: impossible de modifier les informations d'en-tête - en-têtes déjà envoyés par ( sortie démarrée à /some/file.php:12 ) dans /some/file.php sur la ligne 23
Les lignes mentionnées dans les messages d'erreur contiennent header()
et setcookie()
appellent.
Quelle pourrait en être la raison? Et comment y remédier?
ob_start
etob_end_clean()
peut s'avérer utile ici). Vous pouvez ensuite définir un cookie ou une session égal àob_get_contents()
, puis utiliserob_end_clean()
pour effacer le tampon.safeRedirect
fonction dans ma bibliothèque PHP: github.com/heinkasner/PHP-Library/blob/master/extra.phpUTF-8
, maisUTF-8 (Without BOM)
~~~~~~~~~~~Réponses:
Pas de sortie avant d'envoyer des en-têtes!
Les fonctions qui envoient / modifient des en-têtes HTTP doivent être appelées avant toute sortie . summary ⇊ Sinon, l'appel échoue:
Certaines fonctions modifiant l'en-tête HTTP sont:
header
/header_remove
session_start
/session_regenerate_id
setcookie
/setrawcookie
La sortie peut être:
Involontaire:
<?php
ou après?>
Intentionnel:
print
,echo
Et d' autres fonctions fournissant une sortie<html>
antérieur des sections brutes<?php
.Pourquoi cela arrive-t-il?
Pour comprendre pourquoi les en-têtes doivent être envoyés avant la sortie, il est nécessaire de regarder une réponse HTTP typique . Les scripts PHP génèrent principalement du contenu HTML, mais transmettent également un ensemble d'en-têtes HTTP / CGI au serveur Web:
La page / sortie suit toujours les en-têtes. PHP doit d'abord transmettre les en-têtes au serveur Web. Il ne peut le faire qu'une seule fois. Après le double saut de ligne, il ne pourra plus les modifier.
Lorsque PHP reçoit la première sortie (
print
,echo
,<html>
) il chasse d' eau tous les en- têtes collectées. Ensuite, il peut envoyer toutes les sorties souhaitées. Mais l'envoi d'autres en-têtes HTTP est alors impossible.Comment savoir où la sortie prématurée s'est produite?
L'
header()
avertissement contient toutes les informations pertinentes pour localiser la cause du problème:Ici, «ligne 100» fait référence au script où l'
header()
invocation a échoué.La note " sortie commencée à " entre parenthèses est plus significative. Il dénomme la source de la production précédente. Dans cet exemple, c'est
auth.php
et line52
. C'est là que vous avez dû rechercher une sortie prématurée.Causes typiques:
Impression, écho
La sortie intentionnelle de
print
et lesecho
instructions mettront fin à la possibilité d'envoyer des en-têtes HTTP. Le flux d'application doit être restructuré pour éviter cela. Utilisez des fonctions et des modèles de modèles. Assurezheader()
- vous que les appels se produisent avant que les messages ne soient écrits.Les fonctions qui produisent une sortie incluent
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.
Zones HTML brutes
Les sections HTML non analysées dans un
.php
fichier sont également sorties directement. Les conditions de script qui déclencheront unheader()
appel doivent être notées avant tout<html>
bloc brut .Utilisez un modèle de modèle pour séparer le traitement de la logique de sortie.
Espace avant
<?php
pour les avertissements "script.php ligne 1 "Si l'avertissement fait référence à une sortie en ligne
1
, il s'agit principalement d' espaces , de texte ou de HTML en tête avant le<?php
jeton d' ouverture .De même, cela peut se produire pour des scripts ou des sections de script ajoutés:
PHP mange en fait un seul saut de ligne après la fermeture des balises. Mais cela ne compensera pas les nouvelles lignes ou les tabulations ou les espaces décalés dans de tels écarts.
BOM UTF-8
Les sauts de ligne et les espaces seuls peuvent être un problème. Mais il y a aussi des séquences de caractères "invisibles" qui peuvent provoquer cela. Le plus connu est la nomenclature UTF-8 (Byte-Order-Mark) qui n'est pas affichée par la plupart des éditeurs de texte. Il s'agit de la séquence d'octets
EF BB BF
, qui est facultative et redondante pour les documents encodés en UTF-8. PHP doit cependant le traiter comme une sortie brute. Il peut apparaître sous la forme de caractères
dans la sortie (si le client interprète le document en latin-1) ou des "ordures" similaires.En particulier, les éditeurs graphiques et les IDE basés sur Java sont inconscients de sa présence. Ils ne le visualisent pas (obligé par la norme Unicode). Cependant, la plupart des éditeurs de programmeurs et de consoles font:
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 fichier / paramètres (le Bloc-notes ++ sur Windows peut identifier et résoudre le problème ). Une autre option pour inspecter la présence de nomenclatures consiste à recourir à un hexeditor . Les systèmes * nix
hexdump
sont généralement disponibles, sinon une variante graphique qui simplifie l'audit de ces problèmes et d'autres:Une solution simple consiste à définir l'éditeur de texte pour enregistrer les fichiers en tant que "UTF-8 (pas de nomenclature)" ou une autre nomenclature similaire. Souvent, les nouveaux arrivants recourent à la création de nouveaux fichiers et copient et collent simplement le code précédent.
Utilitaires de correction
Il existe également des outils automatisés pour examiner et réécrire les fichiers texte (
sed
/awk
ourecode
). Pour PHP en particulier, il y a lephptags
tag tidier . Il réécrit les balises de fermeture et d'ouverture en formes longues et courtes, mais résout également facilement les problèmes d'espaces blancs de début et de fin, Unicode et UTF-x:Il est raisonnable de l'utiliser sur un répertoire d'inclusion ou de projet.
Espace après
?>
Si la source d'erreur est mentionnée comme derrière la fermeture,
?>
c'est là que des espaces ou du texte brut ont été écrits. Le marqueur de fin PHP ne termine pas l'exécution du script à ce stade. Tous les caractères de texte / espace après cela seront toujours écrits en tant que contenu de page.Il est généralement conseillé, en particulier aux nouveaux arrivants, que les
?>
balises de fermeture PHP de fin soient omises. Cela évite une petite partie de ces cas. (Très souvent, lesinclude()d
scripts sont le coupable.)Source d'erreur mentionnée comme "Inconnu sur la ligne 0"
Il s'agit généralement d'une extension PHP ou d'un paramètre php.ini si aucune source d'erreur n'est concrétisée.
gzip
paramètre d'encodage du flux ou leob_gzhandler
.extension=
module doublement chargé générant un message implicite de démarrage / avertissement PHP.Messages d'erreur précédents
Si une autre instruction ou expression PHP provoque l'impression d'un message ou d'un avertissement, cela compte également 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 avec, par exemple,
isset()
ou@()
- lorsque l'un ou l' autre n'entrave pas le débogage plus tard.Pas de message d'erreur
Si vous avez
error_reporting
oudisplay_errors
désactivé parphp.ini
, aucun avertissement ne s'affichera. Mais ignorer les erreurs ne fera pas disparaître le problème. Les en-têtes ne peuvent toujours pas être envoyés après une sortie prématurée.Ainsi, lorsque les
header("Location: ...")
redirections échouent silencieusement, il est très conseillé de rechercher des avertissements. Réactivez-les avec deux commandes simples au sommet du script d'invocation:Ou
set_error_handler("var_dump");
si tout le reste échoue.En parlant d'en-têtes de redirection, vous devez souvent utiliser un idiome comme celui-ci pour les chemins de code finaux:
De préférence même une fonction utilitaire, qui imprime un message utilisateur en cas de
header()
panne.Tampon de sortie comme solution de contournement
La mise en mémoire tampon de sortie PHP est une solution de contournement pour résoudre ce problème. Il fonctionne souvent de manière fiable, mais ne doit pas se substituer à une bonne structuration de l'application et à la séparation de la sortie de la logique de contrôle. Son objectif réel est de minimiser les transferts par blocs vers le serveur Web.
Le
output_buffering=
cadre peut néanmoins aider. Configurez-le dans le php.ini ou via .htaccess ou même .user.ini sur les configurations FPM / FastCGI modernes.L'activer permettra à PHP de tamponner la sortie au lieu de la transmettre instantanément au serveur Web. PHP peut donc agréger les en-têtes HTTP.
Il peut également être engagé avec un appel au
ob_start();
sommet du script d'invocation. Ce qui est cependant moins fiable pour plusieurs raisons:Même s'il
<?php ob_start(); ?>
démarre le premier script, les espaces ou une nomenclature peuvent être mélangés avant, ce qui le rend inefficace .Il peut cacher des espaces pour la sortie HTML. Mais dès que la logique d'application tente d'envoyer du contenu binaire (une image générée par exemple), la sortie étrangère en mémoire tampon devient un problème. (Nécessaire
ob_clean()
comme solution de contournement supplémentaire.)Le tampon est de taille limitée et peut facilement dépasser lorsqu'il est laissé aux valeurs par défaut. Et ce n'est pas rare non plus, difficile à retrouver quand cela se produit.
Les deux approches peuvent donc devenir peu fiables - en particulier lors du basculement entre les configurations de développement et / ou les serveurs de production. C'est pourquoi la mise en mémoire tampon de sortie est largement considérée comme une béquille / strictement une solution de contournement.
Voir également l' exemple d'utilisation de base dans le manuel, et pour plus d'avantages et d'inconvénients:
Mais cela a fonctionné sur l'autre serveur!?
Si vous n'avez pas reçu d'avertissement d'en-tête auparavant, le paramètre de mise en mémoire tampon de sortie 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 sonder s'il est toujours possible d'envoyer des en-têtes. Ce qui est utile pour imprimer conditionnellement une information ou appliquer une autre logique de secours.Les solutions de rechange utiles sont:
HTML
<meta>
tagSi votre application est structurellement difficile à corriger, un moyen simple (mais quelque peu non professionnel) d'autoriser les redirections consiste à injecter une
<meta>
balise HTML . Une redirection peut être réalisée avec:Ou avec un court délai:
Cela conduit à un code HTML non valide lorsqu'il est utilisé après la
<head>
section. La plupart des navigateurs l'acceptent toujours.Redirection JavaScript
Comme alternative, une redirection JavaScript peut être utilisée pour les redirections de page:
Bien que cela soit souvent plus conforme à HTML que la
<meta>
solution de contournement, cela implique une dépendance à l'égard des clients compatibles JavaScript.Les deux approches font cependant des solutions de rechange acceptables lorsque les appels HTTP header () authentiques échouent. Idéalement, vous combinez toujours cela avec un message convivial et un lien cliquable en dernier recours. (Ce qui est par exemple ce que fait l' extension http_redirect () PECL.)
Pourquoi
setcookie()
etsession_start()
sont également touchésLes deux
setcookie()
etsession_start()
doivent envoyer unSet-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ées.(Bien sûr, ils sont en outre affectés par les cookies désactivés dans le navigateur, ou même par des problèmes de proxy. La fonctionnalité de session dépend évidemment aussi de l'espace disque libre et d'autres paramètres php.ini, etc.)
Liens supplémentaires
la source
?>
de la fin d'un fichier php est généralement une bonne pratique qui permet également de minimiser ces erreurs. Les espaces blancs indésirables ne se produiront pas à la fin des fichiers et vous pourrez toujours ajouter des en-têtes à la réponse plus tard. Il est également pratique si vous utilisez la mise en mémoire tampon de sortie et que vous ne souhaitez pas voir d'espace blanc indésirable ajouté à la fin des parties générées par les fichiers inclus.Ce message d'erreur est déclenché lorsque quelque chose est envoyé avant d'envoyer des en-têtes HTTP (avec
setcookie
ouheader
). Les raisons courantes de produire quelque chose avant les en-têtes HTTP sont:Espaces blancs accidentels, souvent au début ou à la fin des fichiers, comme ceci:
Pour éviter cela, il suffit de laisser de côté la fermeture
?>
- ce n'est pas obligatoire de toute façon.3F 3C
. Vous pouvez supprimer la nomenclature en toute sécuritéEF BB BF
au début des fichiers.echo
,printf
,readfile
,passthru
, code avant<?
etc.display_errors
propriété php.ini est définie. Au lieu de planter sur une erreur de programmation, php corrige silencieusement l'erreur et émet un avertissement. Bien que vous puissiez modifier les configurationsdisplay_errors
ou error_reporting , vous devriez plutôt résoudre le problème.Les raisons courantes sont les accès aux éléments non définis d'un tableau (comme
$_POST['input']
sans utiliserempty
ouisset
pour tester si l'entrée est définie), ou en utilisant une constante non définie au lieu d'un littéral de chaîne (comme dans$_POST[input]
, notez les guillemets manquants).L'activation de la mise en mémoire tampon de sortie devrait faire disparaître le problème; toutes les sorties après l'appel à
ob_start
sont mises en mémoire tampon jusqu'à ce que vous libériez le tampon, par exemple avecob_end_flush
.Cependant, bien que la mise en mémoire tampon de sortie évite les problèmes, vous devez vraiment déterminer pourquoi votre application génère 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 de la météo avant de dire à l'appelant qu'il a le mauvais numéro.
la source
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 peut avoir été provoquée par les espaces vides avant le début du fichier ou après la fin du fichier. Ces espaces vides ne doivent pas être ici.
ex) IL NE DOIT PAS Y AVOIR D'ESPACES BLANCHES ICI
Vérifiez tous les fichiers associés au fichier à l'origine de cette erreur.
Remarque: Parfois, EDITOR (IDE) comme gedit (un éditeur Linux par défaut) ajoute une ligne vierge dans le fichier de sauvegarde. Cela ne devrait pas arriver. Si vous utilisez Linux. vous pouvez utiliser l'éditeur de VI pour supprimer les espaces / lignes après?> à la fin de la page.
Solution possible 2: Si ce n'est pas votre cas, utilisez ob_start pour sortir la mise en mémoire tampon:
Cela activera la mise en mémoire tampon de sortie et vos en-têtes seront créés après la mise en mémoire tampon de la page.
la source
ob_start()
cache juste le problème; ne l'utilisez pas pour résoudre ce problème particulier.ob_start()
, alors que dois-je faire pour résoudre ce problème:Headers already sent
ob_start()
ne "cache" pas le problème, il résout le problème.Au lieu de la ligne ci-dessous
écrire
ou
Cela résoudra certainement votre problème. J'ai rencontré le même problème mais j'ai résolu en écrivant l'emplacement de l'en-tête de la manière ci-dessus.
la source
Tu fais
avant de définir les cookies, ce qui n'est pas autorisé. Vous ne pouvez envoyer aucune sortie avant les en-têtes, pas même une ligne vierge.
la source
C'est à cause de cette ligne:
Vous ne devez rien imprimer / faire écho avant d'envoyer les en-têtes.
la source
PROBLÈMES COMMUNS:
(copié de: source )
====================
1) il ne devrait pas y avoir de sortie (c'est
echo..
-à- dire ou de codes HTML) avant laheader(.......);
commande.2) supprimez tout espace blanc (ou nouvelle ligne ) avant
<?php
et après les?>
balises.3) RÈGLE D'OR! - vérifiez si ce fichier php (et aussi, si vous avez d'
include
autres fichiers) a UTF8 sans encodage BOM (et pas seulement UTF-8 ). C'est un problème dans de nombreux cas (car le fichier encodé UTF8 a quelque chose de spécial au début du fichier php, que votre éditeur de texte ne montre pas) !!!!!!!!!!!!4) Après avoir
header(...);
utiliséexit;
5) utilisez toujours la référence 301 ou 302:
6) Activez le rapport d'erreurs et recherchez l'erreur. Votre erreur peut être due à une fonction qui ne fonctionne pas. Lorsque vous activez le rapport d'erreurs, vous devez toujours corriger l'erreur la plus élevée en premier. Par exemple, il peut s'agir de "Avertissement: date_default_timezone_get (): il n'est pas sûr de s'appuyer sur les paramètres de fuseau horaire du système." - puis plus bas, vous pouvez voir l'erreur "en-têtes non envoyés". Après avoir corrigé l'erreur la plus élevée (1ère), rechargez votre page. Si vous avez encore des erreurs, corrigez à nouveau l'erreur la plus élevée.
7) Si rien de ce qui précède ne vous aide, utilisez la redirection JAVSCRIPT (cependant, méthode fortement non recommandée), peut être la dernière chance dans les cas personnalisés ...:
la source
301
ou302
important?Un conseil simple: un simple espace (ou caractère spécial invisible) dans votre script, juste avant la toute première
<?php
balise, peut provoquer cela! Surtout lorsque vous travaillez en équipe et que quelqu'un utilise un IDE «faible» ou a gâché les fichiers avec d'étranges éditeurs de texte.J'ai vu ces choses;)
la source
Une autre mauvaise pratique peut invoquer ce problème qui n'est pas encore indiqué.
Voir cet extrait de code:
Les choses vont bien, non?
Et si "a_important_file.php" est ceci:
Cela ne fonctionnera pas? Pourquoi? Parce que déjà une nouvelle ligne est générée.
Maintenant, bien que ce ne soit pas un scénario courant, que se passe-t-il si vous utilisez un framework MVC qui charge beaucoup de fichiers avant de transférer des choses à votre contrôleur? Ce n'est pas un scénario rare. Soyez prêt pour cela.
Depuis PSR-2 2.2:
Unix LF (linefeed) line ending
.single blank line
.omitted
de fichiers contenantonly php
Croyez-moi, suivre ces normes peut vous faire économiser beaucoup d'heures de votre vie :)
la source
?>
en aucun cas mettre la balise de fermeture dans un fichierCR LF
(fin de ligne Windows typique). Je le résout en téléchargeant le fichier d'origine à partir du dépôt Wordpress qui aLF
(fin de ligne Linux) au lieu deCR LF
et j'ai également déplacé ma fonction vers le fichier functions.php du thème. Basé sur: bit.ly/1Gh6mzN?>
<?php
, supprimer et ajouter une seule ligne vierge, ajouté et omis une balise de fermeture?>
. Dans Windows + Wamp, toutes ces combinaisons fonctionnent correctement. Wierd ...Parfois, lorsque le processus de développement a à la fois des stations de travail WIN et des systèmes LINUX (hébergement) et dans le code, vous ne voyez aucune sortie avant la ligne associée, il peut s'agir du formatage du fichier et de l'absence de fin de ligne Unix LF (linefeed) .
Ce que nous faisons habituellement pour résoudre rapidement ce problème, c'est renommer le fichier et sur le système LINUX créer un nouveau fichier au lieu du renommé, puis copier le contenu dans celui-ci. Plusieurs fois, cela résout le problème car certains des fichiers créés dans WIN une fois déplacés vers l'hébergement provoquent ce problème.
Ce correctif est un correctif facile pour les sites que nous gérons par FTP et peut parfois faire gagner du temps aux nouveaux membres de notre équipe.
la source
Généralement, cette erreur survient lorsque nous envoyons un en-tête après un écho ou une impression. Si cette erreur survient sur une page spécifique, assurez-vous que cette page ne fait aucun écho avant d'appeler
start_session()
.Exemple d'erreur imprévisible:
Un autre exemple:
Conclusion: ne sortez aucun caractère avant d'appeler
session_start()
ouheader()
ne fonctionne même pas un espace blanc ou une nouvelle lignela source