Lors de l'exécution de mon script, j'obtiens plusieurs erreurs comme celle-ci :
Attention : Impossible de modifier les informations d'en-tête - en-tête déjà envoyé par/some/file.php(La sortie commence à /some/file.php:12)
La ligne mentionnée dans le message d'erreur contient l'appelheader()
和setcookie()
.
Quelle pourrait en être la raison ? Comment le résoudre?
Envoyez quoi que ce soit avant d'envoyer les en-têtes HTTP (utilisez
setcookie
或header
). Les raisons courantes pour lesquelles quelque chose est affiché avant les en-têtes HTTP sont :Espaces inattendus, généralement au début ou à la fin d'un fichier, comme ceci :
Pour éviter cela, omettez simplement la fin
?>
- ce n'est pas nécessaire de toute façon.La- marque d'ordre des octetsest située au début des fichiers PHP. Vérifiez votre fichier php à l'aide d'un éditeur hexadécimal pour voir si tel est le cas. Ils devraient être en octets
- Sortie explicite, telle qu'appeler
- Avertissements générés par php si la propriété
ou
pour tester si l'entrée est définie), Ou utilisez une constante non définie au lieu d'une chaîne littérale (comme dans3F 3C
开头。您可以安全地从文件开头删除 BOMEF BB BF
.echo
、printf
、readfile
、passthru
、之前的代码>
etc.display_errors
display_errors
php.ini属性已设置。 php 不会因程序员错误而崩溃,而是默默地修复错误并发出警告。虽然您可以修改display_errors
php.ini est définie. Au lieu de planter à cause d'une erreur du programmeur, php corrige silencieusement l'erreur et émet un avertissement. Bien que vous puissiez modifier la configurationdisplay_errors
ouerror_reportinget vous devriez résoudre le problème.
$_POST['input']
而不使用empty
或isset
进行测试是否设置了输入),或者使用未定义的常量而不是字符串文字(如$_POST[input]
Une cause fréquente est l'accès à des éléments non définis dans le tableau (par exemple$_POST['input']
sans utiliserempty
isset
$_POST[input]
, notez les guillemets manquants).Activez lamise en mémoire tampon de sortie
sont mises en mémoire tampon jusqu'à ce que vous libériez le tampon, par exemple avecob_start
后的所有输出都缓冲在内存中,直到您释放缓冲区,例如与ob_end_flush
devrait faire l'affaire ; toutes les sorties après l'appel deob_start
ob_end_flush
.
Cependant, même si la mise en mémoire tampon de sortie peut éviter ces problèmes, vous devez vraiment déterminer pourquoi votre application génère le corps HTTP avant les en-têtes HTTP. C'est comme répondre au téléphone et discuter de votre journée et de la météo, puis dire à l'appelant qu'il a composé le mauvais numéro.Aucune sortie avant l'envoi des en-têtes !
Les fonctions qui envoient/modifient les en-têtes HTTP doivent être appelées avant qu'une sortie ne soit effectuée.Résumé⇊Sinon l'appel échoue :
Certaines fonctions qui modifient les en-têtes HTTP sont :
En-tête
标题
/header_remove
/header_remove
session_start
session_start
/session_regenerate_id
/session_regenerate_id
setcookie
setcookie
/setrawcookie
/setrawcookie
La sortie peut être :
Involontaire :
L'espace après
- SpécifiqueMarque d'ordre UTF-8 octets
- Message d'erreur ou notification précédente
之前或
?>
Délibérément :
print
、echo
et autres fonctions qui produisent une sortie代码之前的原始
partie.
Pourquoi cela arrive-t-il ?
Il est nécessaire de comprendre pourquoi les en-têtes doivent être envoyés avant la sortie Voir typiqueHTTPrépondre. Le script PHP génère principalement du contenu HTML et transmet également un Ensemble d'entêtes HTTP/CGI envoyés au serveur web :
Page/Sortiesuit toujourstitre. PHP doit réussir L'en-tête est d'abord envoyé au serveur Web. Cela ne peut être fait qu'une seule fois. Ils ne peuvent plus être modifiés après double emballage.
Lorsque PHP reçoit la première sortie (
print
、echo
、,
), il seraActualisertous les en-têtes collectés. Après cela, il peut envoyer toutes les sorties Il le veut. Mais l'envoi d'autres en-têtes HTTP n'est pas possible.
Comment savoir où se produit une sortie prématurée ?
header()
L'avertissement contient toutes les informations pertinentes Cause du problème de positionnement :Ici, « ligne 100 » fait référence au script qui
header()
appelleet échoue.Le commentaire "la sortie commence à" entre parenthèses est plus important. Il représente la source de la sortie précédente. Dans cet exemple, c'est
auth.php
etème ligne52
. C'est là qu'il faut rechercher une sortie prématurée.Raisons typiques :
Imprimer et écho
La sortie intentionnelle de l'instructionprint
和echo
mettra fin à la possibilité d'envoyer des en-têtes HTTP. Le processus de candidature doit être restructuré pour éviter cette situation. Utilisation de la fonctionet des solutions de modèles. Assurez-vous que l'appelheader()
a lieu avant le messageTout est écrit.Les fonctions qui produisent une sortie incluent
打印
、echo
、printf
、vprintf
trigger_error
、ob_flush
、ob_end_flush
、var_dump
、print_r
readfile
、passthru
、flush
、imagepng
、imagejpeg
Et d'autres fonctions définies par l'utilisateur.
Zone HTML originale
La partie HTML non analysée du fichier .php est également sortie directement. Il faut faire attention aux conditions du script qui déclencheront l'appel
header()
Avanttoutblocoriginal.
L'espace avant signifie "script.phpLigne 1" avertissement
Si l'avertissement fait référence à la sortie en ligne
1
, alors principalement Débutespaceavant la balise d'ouverture, texte ou HTML.
NOMME UTF-8
Les nouvelles lignes et les espaces peuvent à eux seuls poser problème. Mais il y a aussi des « invisibles » Séquences de caractères pouvant provoquer cela. Le plus célèbre estUTF-8 BOM(Marque d'ordre des octets)La plupart des éditeurs de texte ne l'affichent pas. C'est une séquence d'octets
EF BB BF
,对于 UTF-8 编码的文档来说,它是可选且冗余的。然而 PHP 必须将其视为原始输出。它可能在输出中显示为字符
(si le client interprète le document comme Latin-1) ou une « poubelle » similaire.Surtout les éditeurs graphiques et les IDE basés sur Java ne le remarquent pas Être présent. Ils ne le visualisent pas (comme l'exige la norme Unicode). Cependant, la plupart des programmeurs et éditeurs de consoles :
Cela facilite la détection précoce des problèmes. D'autres éditeurs peuvent reconnaître Il est présent dans le menu Fichier/Paramètres (Notepad++ sous Windows reconnaît etProblème résolu), Une autre option pour vérifier l'existence de la nomenclature est d'utiliser l'Hex Editor. Sur les systèmes *nix
hexdump
généralement disponibles, Sinon, simplifiez l'examen des variantes graphiques de ces questions et d'autres :Une solution simple consiste à configurer votre éditeur de texte pour qu'il enregistre les fichiers au format "UTF-8 (pas de nomenclature)". Ou une nomenclature similaire. Souvent, les débutants auront recours à la création de nouveaux fichiers, puis à copier et coller le code précédent.
Utilitaire de correction
Il existe également des outils automatisés pour vérifier et réécrire les fichiers texte (
sed
/awk
sed
/awk代码>
或重新编码
ourecode
). Pour PHP, plus précisément la balisephptags
plus rangée. Il réécrit les balises de fermeture et d'ouverture sous forme longue et courte et est également simple. Correction des espaces de début et de fin, des problèmes de nomenclature Unicode et UTF-x :Utilisation sûre sur des répertoires d'inclusion ou de projet entiers.
后有空格?>
Si la source de l'erreur est mentionnée plus tardFermer
?>
Eh bien, c'est ici qu'un texte vierge ou brut est écrit. La balise de fermeture PHP ne termine pas l'exécution du script pour le moment. Tous les caractères de texte/espace après seront écrits en tant que contenu de la page toujours.Il est généralement recommandé, notamment aux débutants, de suivre
?>
PHP La balise de fermeture doit être omise. Celaéviteune petite fraction de ces cas. (Très courant, les scriptsinclude()d
sont les coupables.)La source de l'erreur s'appelle "Ligne inconnue 0"
S'il n'y a pas de source d'erreur, il s'agit généralement d'une extension PHP ou d'un paramètre php.ini Béton.
gzip
Paramètres d'encodage du fluxouob_gzhandler
.extension=
à double charge Générez des messages de démarrage/avertissement PHP implicites.Message d'erreur précédent
Si une autre instruction ou expression PHP provoque un message d'avertissement ou Une note est imprimée, ce qui est également considéré comme une sortie prématurée.
Dans ce cas, vous devez éviter les erreurs, Retardez l'exécution de l'instruction ou supprimez les messages en utilisant par ex.
isset()
isset()
或@()
ou@()
- Quand l’un ou l’autre n’empêche pas le débogage ultérieur.Aucun message d'erreur
Si vous vous basez sur
php.ini
禁用了error_reporting
或display_errors
, Aucun avertissement n’apparaîtra alors. Mais ignorer l'erreur ne résout pas le problème partir. Toujours impossible d'envoyer des en-têtes après une sortie prématurée.Alors quand
header("Location: ...")
une redirection échoue silencieusement, c'est très grave Un avertissement de sonde est recommandé. Réactivez-les avec deux commandes simples En plus du script d'appel :ou
set_error_handler("var_dump");
si tout le reste échoue.En parlant d'en-têtes de redirection, vous devriez toujours utiliser des expressions comme celle-ci Voici le chemin de code final :
Il est préférable d'être une fonction pratique qui imprime les messages des utilisateurs Si
header()
échoue.Mise en mémoire tampon de sortie comme solution de contournement
PHPTampon de sortieest une solution de contournement pour atténuer ce problème. Cela fonctionne généralement de manière fiable, mais cela ne devrait pas Remplacer la structure d'application correcte et séparer la sortie du contrôle logique. Son objectif réel est de minimiser les transferts fragmentés vers le serveur Web.
output_buffering=
Pourtant, les paramètres aident. Configurez-le dansphp.iniOu via.htaccessMême.user.iniConfiguration FPM/FastCGI moderne.L'activation de cette option permettra à PHP de mettre en mémoire tampon la sortie au lieu de la transmettre immédiatement au serveur Web. PHP peut donc agréger les en-têtes HTTP.
On peut aussi l'appeler en appelant
ob_start();
au-dessus du script appelant. Cependant, il n'est pas très fiable pour plusieurs raisons :Même si
démarre le premier script, un espace ou La nomenclature peut être brouillée et invalidée avant lerendu.
Il peut masquer les espaces de la sortie HTML. Cependant, une fois que la logique de l'application tente d'envoyer du contenu binaire (comme une image générée), La sortie étrangère en mémoire tampon devient un problème. (nécessite ob_clean()) comme solution de contournement supplémentaire. )
La taille du tampon est limitée et peut facilement déborder si elle est laissée à la valeur par défaut. Cette situation n'est pas rare,difficile à suivre一个> quand ça arrive.
Par conséquent, les deux méthodes peuvent devenir peu fiables, en particulier lors du basculement entre les deux. Configuration du développement et/ou serveur de production. C'est pourquoi la mise en mémoire tampon de sortie est Largement considéré comme n'étant qu'une béquille/strictement une solution de contournement.
Voir aussiExemples d'utilisation de baseDans le manuel, et plus d'avantages et d'inconvénients :
Mais ça marche sur d'autres serveurs ! ?
Si vous n'avez pas reçu l'avertissement d'en-tête auparavant,mise en mémoire tampon de sortie Paramètres php.inidéjà changé. Il n'est peut-être pas configuré sur le serveur actuel/nouveau.
Utilisez
headers_sent()检查
Vous pouvez toujours utiliser
headers_sent()
pour détecter si Il est toujours possible... d'envoyer des en-têtes. Ceci est utile pour l'impression conditionnelle informations ou appliquer une autre logique de secours.Une solution de repli utile est :
HTML
balise
Si votre application est structurellement difficile à corriger, un simple (mais Un peu peu professionnel) La façon d'autoriser la redirection est d'injecter du HTML
Balises. La redirection peut être réalisée via :
Ou court délai :
Cela entraîne un HTML invalide lorsqu'il est utilisé au-delà de la section
. La plupart des navigateurs l'acceptent toujours.
Redirection JavaScript
Comme alternative,Redirections JavaScriptDisponible pour la redirection de page :
Bien que cette solution soit généralement plus conforme au HTML que la solution de contournement
, Cela entraîne une dépendance vis-à-vis des clients compatibles JavaScript.
Cependant, les deux méthodes produisent des solutions de repli acceptables lorsque le véritable en-tête HTTP() L'appel a échoué. Idéalement, vous combinez toujours cela avec un message convivial, Liens cliquables en dernier recours. (Par exemple,http_redirect()L'extension PECL le fait. )
Pourquoi
setcookie()
和session_start()
est également concernésetcookie()
和session_start()
都需要发送Set-Cookie:
En-têtes HTTP. Par conséquent, les mêmes conditions s'appliquent et un message d'erreur similaire sera généré Utilisé en cas de sortie prématurée.(Bien entendu, ils sont également concernés par la désactivation des cookies dans votre navigateur Même des problèmes d’agence. La fonctionnalité de session s'appuie évidemment aussi sur la gratuité Espace disque et autres paramètres php.ini, etc.)
Plus de liens