web-dev-qa-db-fra.com

Pourquoi omettrait-on la balise close?

Je continue à lire, il est peu pratique d’utiliser la balise de fermeture PHP ?> à la fin du fichier. Le problème de l'en-tête semble sans importance dans le contexte suivant (et c'est le seul argument valable à ce jour):

Les versions modernes de PHP définissent l'indicateur output_buffering dans php.ini. Si la mise en mémoire tampon de sortie est activée, vous pouvez définir des en-têtes HTTP et des cookies après la sortie du code HTML, car le code renvoyé n'est pas envoyé au navigateur immédiatement.

Chaque bon livre de pratique et wiki commence par cette "règle", mais personne ne donne de bonnes raisons. Existe-t-il une autre bonne raison de ne pas utiliser la balise de fin PHP?

361
danidacar

L'envoi d'en-têtes plus tôt que le cours normal peut avoir de lourdes conséquences. Voici quelques-unes d’entre elles qui m’étaient venues à l’esprit en ce moment:

  1. Bien que les versions actuelles PHP puissent avoir la mise en tampon de sortie activée, les serveurs de production réels sur lesquels vous déploierez votre code sont bien plus importants que toute machine de développement ou de test. Et ils n'ont pas toujours tendance à suivre immédiatement les dernières tendances PHP.

  2. Vous pouvez avoir des maux de tête suite à une perte de fonctionnalité inexplicable . Disons que vous implémentez une sorte de passerelle de paiement et redirigez l'utilisateur vers une URL spécifique après confirmation avec succès par le processeur de paiement. Si une sorte d'erreur PHP, même un avertissement ou une fin de ligne excessive, se produit, le paiement peut rester non traité et l'utilisateur peut sembler non facturé. C’est également l’une des raisons pour lesquelles une redirection inutile est un mal et si elle est utilisée, elle doit être utilisée avec prudence.

  3. Vous pouvez obtenir des erreurs de type "Chargement de la page annulé" dans Internet Explorer, même dans les versions les plus récentes. Ceci est dû au fait que la réponse/json include AJAX contient quelque chose qu’elle ne devrait pas contenir, à cause des fins de ligne excédentaires dans certains PHP fichiers, comme je l’ai rencontré il ya quelques jours.

  4. Si vous avez des téléchargements de fichiers dans votre application, ils peuvent également rompre, pour cette raison. Et vous ne le remarquerez peut-être pas, même après des années, car l'habitude particulière du téléchargement dépend du serveur, du navigateur, du type et du contenu du fichier (et éventuellement d'autres facteurs avec lesquels je ne veux pas vous ennuyer) .

  5. Enfin, de nombreux PHP frameworks comprenant Symfony , Zend et Laravel (il n'y a aucune mention de cela dans le directives de codage mais il en est ainsi) et le norme PSR-2 (élément 2.2) exige l’omission de l’étiquette de fermeture. PHP manuel lui-même ( 1 , 2 ), Wordpress , Drupal et beaucoup d'autres PHP logiciel, je suppose, conseiller de le faire. Si vous prenez simplement l'habitude de suivre la norme (et la configuration PHP-CS-Fixer pour votre code), vous pouvez oublier le problème. Sinon, vous devrez toujours garder la question à l’esprit.

Bonus: quelques pièges (actuellement un) liés à ces 2 personnages:

  1. Même certaines bibliothèques bien connues peuvent contenir des fins de ligne en excès après ?>. Smarty en est un exemple. Même les versions les plus récentes des branches 2. * et 3. * l’ont. Donc, comme toujours, surveillez le code tiers . Bonus en bonus: Une expression rationnelle pour supprimer des fins inutiles PHP: remplacez (\s*\?>\s*)$ par un texte vide dans tous les fichiers contenant le code PHP.
314
Halil Özgür

La raison pour laquelle vous devez laisser la balise php de fermeture (?>) est pour que le programmeur n'envoie pas accidentellement de caractères de nouvelle ligne.

La raison pour laquelle vous ne devriez pas laisser la balise php de fermeture est parce qu'elle provoque un déséquilibre dans les balises php et que tout programmeur avec une demi-tête d'esprit peut se rappeler de ne pas ajouter d'espace supplémentaire.

Donc pour votre question:

Existe-t-il une autre bonne raison de ne pas utiliser la balise php de fin?

Non, il n'y a pas ne autre bonne raison pour ignorer les balises php de fin.

Je vais terminer avec quelques arguments pour ne pas se soucier de la balise de fermeture:

  1. Les gens sont toujours capables de faire des erreurs, peu importe leur intelligence. Adhérer à une pratique qui réduit le nombre d'erreurs possibles est (à mon humble avis) une bonne idée.

  2. PHP n'est pas XML. PHP n'a pas besoin de respecter les normes strictes de XML pour être bien écrit et fonctionnel. Si une balise de fermeture manquante vous agace, vous êtes autorisé à utiliser une balise de fermeture. Ce n'est pas une règle définie dans la pierre ni dans un sens ni dans l'autre.

120
zzzzBov

C'est une recommandation de style de débutant, bien intentionnée et conseillée par le manuel .

  • Eschewing _?>_ résout cependant juste n filet ​​du commun causes déjà envoyées causes (sortie brute, BOM , avis, etc. .) et leurs problèmes de suivi.

  • PHP contient en fait de la magie pour manger des sauts de ligne après le jeton de fermeture _?>_. Même si cela a numéros historiques , et laisse les nouveaux arrivants encore vulnérables aux éditeurs floconneux et aux déplacements inopinés dans d’autres espaces après _?>_.

  • De manière stylistique, certains développeurs préfèrent afficher _<?php_ et _?>_ en tant que balises SGML/instructions de traitement XML, ce qui implique la cohérence de la balance d'un jeton de fin. (Lequel, est utile pour la classe dépendante-dépendante inclut de supplanter le chargement automatique inefficace fichier par fichier.)

  • Ce qui est assez rare, l’ouverture _<?php_ est caractérisée par PHP Shebang (et parfaitement réalisable par binfmt_misc ), validant ainsi la redondance d’une balise fermée correspondante .

  • Il existe une contradiction évidente entre guides de syntaxe classiques PHP mandating _?>\n_ et le plus les plus récents (PSR-2) acceptant les omissions.
    (Pour mémoire: Zend Framework postulant l’un sur l’autre n’implique pas sa supériorité inhérente. C’est une idée fausse que les experts aient été attirés par le public cible d’API peu maniables).

  • SCMs et IDE modernes fournir des solutions intégrées principalement soulageant le gardiennage de proximité.

Décourager l'utilisation de la balise close _?>_ ne fait que retarder l'explication du comportement de traitement de base PHP et de la sémantique du langage, afin d'éviter les problèmes peu fréquents. Il est pratique toujours pour le développement logiciel collaboratif en raison des variations de compétence des participants.

Fermer les variations de balises

  • Le normal ?> La balise close est également appelée T_CLOSE_TAG , ou "jeton proche".

  • Il comprend quelques incarnations supplémentaires, à cause de la magie des PHP newline eating:

    ?>\n (Saut de ligne Unix)

    ?>\r (Retour chariot, MACs classiques)

    ?>\r\n (CR/LF, sous DOS/Win)

    PHP ne supporte pas le saut de ligne combo Unicode NEL (U + 0085) cependant.

    Les premières versions PHP avaient des compilations IIRC limitant quelque peu l'agnosticisme de plate-forme (FI vient même d'utiliser _>_ comme marqueur proche), qui est probablement l'origine historique de l'évitement de balises fermées.

  • Souvent négligé, mais jusqu’à PHP7 les supprime , le _<?php_ Le jeton d'ouverture peut être valablement couplé avec le rarement utilisé _</script>_ comme jeton de fermeture impair.

  • Le "balise close étroite" n'en est même pas un - il a simplement inventé ce terme pour l'analogie. Sur le plan de la conception et de l’utilisation __halt_compiler devrait cependant être reconnu comme proche.

    ___HALT_COMPILER();
    ?>
    _

    Ce qui signifie que le tokenizer supprime tout code ou toute section HTML simple par la suite. En particulier, les descripteurs PHAR utilisent cette possibilité ou sa combinaison redondante avec _?>_ comme illustré.

  • De même, un void _return;_ substitue rarement dans des scripts d'inclusion, rendant toute _?>_ avec les espaces finaux non effectifs.

  • Ensuite, il y a toutes sortes de soft/faux variations de balises proches; moins connu et rarement utilisé, mais généralement par commenté jetons:

    • Espacement simple _// ? >_ pour échapper à la détection par tokenizer PHP.

    • Ou substituts Unicode fantaisie _// ﹖﹥_ (Petite question U + FE56, support pour petit angle U + FE65) qu’une expression rationnelle peut saisir.

    Les deux ne signifient rien pour PHP , mais peuvent avoir des utilisations pratiques pour les toolkits externes peu ou pas conscients de PHP. Encore une fois cat- les scripts joints viennent à l’esprit, avec les concaténations résultantes de _// ? > <?php_ qui conservent en ligne l’ancienne section de fichiers.

Il existe donc des alternatives dépendantes du contexte mais pratiques à l'omission impérative d'une balise fermée.

Le baby-sitting manuel de _?>_ balises fermées n’est pas très contemporain non plus. Il y a toujours eu des outils d'automatisation pour cela (même si sed/awk ou regex-oneliners). En particulier:

phptags tag tidier

https://Fossil.include-once.org/phptags/

Ce qui pourrait généralement être utilisé pour _--unclose_ balises php pour le code tiers, ou plutôt simplement pour résoudre tout problème (et tous) réel d'espaces/nomenclatures:

  • _phptags --warn --whitespace *.php_

Il gère également les conversions de balises _--long_ pour la compatibilité exécution/configuration.

55
mario

Ce n'est pas une étiquette…

Mais si vous l'avez, vous risquez d'avoir un espace blanc après.

Si vous l'utilisez ensuite en tant qu'inclusion en haut d'un document, vous risquez de finir par insérer des espaces (avant tout le contenu) avant d'essayer d'envoyer des en-têtes HTTP… non autorisés.

21
Quentin

C'est très utile de ne pas laisser la fermeture ?> dans.

Le fichier reste valide jusqu'au PHP (pas une erreur de syntaxe) et comme @David Dorward l'a dit, cela permet d'éviter d'avoir des espaces/lignes de rupture (tout ce qui peut envoyer un en-tête au navigateur) après le ?>.

Par exemple,

<?
    header("Content-type: image/png");
    $img = imagecreatetruecolor ( 10, 10);
    imagepng ( $img);
?>
[space here]
[break line here]

ne sera pas valide.

Mais

<?
    header("Content-type: image/png");
    $img = imagecreatetruecolor ( 10, 10 );
    imagepng ( $img );

volonté.

Pour une fois, vous devez être paresseux pour être sécurisé.

16
Shikiryu

Selon la documentation , il est préférable d’omettre la balise de fermeture si elle se trouve à la fin du fichier pour la raison suivante:

Si un fichier est du code pur PHP, il est préférable d’omettre la balise de fermeture PHP à la fin du fichier. Cela évite les espaces blancs accidentels ou les nouvelles lignes ajoutés après la balise de fermeture PHP, ce qui peut entraîner des effets indésirables, car PHP commencera à mettre en tampon la sortie lorsqu'il n'y a aucune intention du programmeur d'envoyer une sortie. à ce stade du script.

Manuel PHP> Référence du langage> Syntaxe de base> PHP tags

14
Asaph

Eh bien, il y a deux façons de voir les choses.

  1. Le code PHP n’est rien de plus qu’un ensemble de instructions de traitement XML , et par conséquent, tout fichier portant l’extension .php n’est rien de plus qu’un fichier XML qui doit être analysé pour PHP code.
  2. PHP partage le format d’instruction de traitement XML pour ses balises open et close. Sur cette base, les fichiers avec les extensions .php PEUVENT être des fichiers XML valides, mais ils n’ont pas besoin de l'être.

Si vous croyez la première route, tous les fichiers PHP nécessitent des balises de fin de fermeture. Les omettre créera un fichier XML invalide. Là encore, sans avoir une déclaration d'ouverture <?xml version="1.0" charset="latin-1" ?>, vous ne disposerez de toute façon pas d'un fichier XML valide ... Ce n'est donc pas un problème majeur ...

Si vous croyez le deuxième itinéraire, cela ouvre la porte à deux types de fichiers .php:

  • Fichiers contenant uniquement du code (fichiers de bibliothèque par exemple)
  • Fichiers contenant du code XML natif et du code (fichiers de modèle par exemple)

Sur cette base, les fichiers de code uniquement peuvent se terminer sans balise de fermeture ?>. Mais les fichiers de code XML ne peuvent pas se terminer sans un ?> de fermeture, car cela invaliderait le XML.

Mais je sais à quoi tu penses. Vous pensez que ce qui compte, vous ne pourrez jamais restituer un fichier PHP directement, alors, que se soucie-t-il de savoir si c'est du XML valide? Eh bien, cela importe si vous concevez un modèle. Si c'est XML/HTML valide, un navigateur normal n'affichera simplement pas le code PHP (c'est traité comme un commentaire). Vous pouvez donc simuler le modèle sans avoir à exécuter le code PHP dans ...

Je ne dis pas que c'est important. C'est juste un point de vue que je ne vois pas être exprimé trop souvent, alors quel meilleur endroit pour le partager ...

Personnellement, je ne ferme pas les balises dans les fichiers de bibliothèque, mais dans les fichiers de modèle ... Je pense que c'est une préférence personnelle (et une directive de codage) basée plus que tout ce qui est difficile ...

9
ircmaxell

Eh bien, je connais la raison, mais je ne peux pas le montrer:

Pour les fichiers contenant uniquement du code PHP, la balise de fermeture (?>) n'est jamais autorisée. Cela n’est pas requis par PHP, et son omission évite l’injection accidentelle d’espaces blancs dans la réponse.

Source: http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html

8
tawfekov

En plus de tout ce qui a déjà été dit, je vais ajouter une autre raison qui a été très pénible pour nous de déboguer.

Apache 2.4.6 avec PHP 5.4 erreurs de segmentation sur nos machines de production lorsqu'il y a un espace vide derrière la balise php de clôture. Je viens de perdre des heures jusqu'à ce que je réduise finalement le bogue avec strace .

Voici l'erreur que lance Apache:

[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)
7

"Y a-t-il une autre bonne raison (à part le problème de l'en-tête) pour ignorer la balise php de fin?"

Vous ne souhaitez pas générer par inadvertance des caractères d'espaces blancs superflus lors de la génération d'une sortie binaire, de données CSV ou de toute autre sortie non HTML.

6
user1238364

Avantages

Les inconvénients

Conclusion

Je dirais que les arguments en faveur de l'omission de la balise semblent plus forts (aide à éviter les gros maux de tête avec header () + c'est une "recommandation" de PHP/Zend). J'admets que ce n'est pas la plus "belle" solution que j'ai jamais vue en termes de cohérence syntaxique, mais quoi de mieux?

5
Frosty Z

Comme ma question a été marquée comme une copie de celle-ci, je pense que c'est O.K. pour poster pourquoi PAS omettre la balise de fermeture ?> peut être souhaité pour certaines raisons.

  • Avec les instructions de traitement complètes, la syntaxe (<?php ... ?>) PHP source est un document SGML valide, qui peut être analysé et traité sans problème avec l'analyseur SGML. Avec des restrictions supplémentaires, il peut également s'agir de XML/XHTML valide.

Rien ne vous empêche d'écrire du code XML/HTML/SGML valide. documentation PHP en est conscient. Extrait:

Remarque: notez également que si vous intégrez PHP dans XML ou XHTML, vous devrez utiliser les balises <? Php?> Pour rester conforme aux normes.

Bien entendu, la syntaxe PHP n'est pas stricte SGML/XML/HTML et vous créez un document, qui n'est pas SGML/XML/HTML, comme si vous pouviez transformer HTML en XHTML pour qu'il soit compatible XML ou non.

  • À un moment donné, vous souhaiterez peut-être concaténer des sources. Ce ne sera pas aussi facile que de simplement faire cat source1.php source2.php si une incohérence est introduite en omettant de fermer les balises ?> de fermeture.

  • Sans ?>, il est plus difficile de dire si le document a été laissé en PHP mode évasion ou PHP en mode ignoré (la balise PI <?php a été ouverte ou non). La vie est plus facile si vous laissez systématiquement vos documents en mode PHP ignore. C'est comme travailler avec des documents HTML bien formatés par rapport à des documents avec des balises non fermées, mal imbriquées, etc.

  • Il semble que certains éditeurs comme Dreamweaver puissent avoir des problèmes avec PI laissé ouvert [1] .

2
doc

Si je comprends bien la question, elle concerne la mise en mémoire tampon de sortie et l’effet que cela pourrait avoir sur les balises fermantes/finales. Je ne suis pas sûr que ce soit une question tout à fait valable. Le problème est que le tampon de sortie ne signifie pas que tout le contenu est conservé en mémoire avant de l'envoyer au client. Cela signifie qu'une partie du contenu est.

Le programmeur peut délibérément vider le tampon, ou le tampon de sortie, donc l'option de tampon de sortie dans PHP change-t-elle réellement l'impact de la balise de fermeture sur le codage? Je dirais que ce n'est pas le cas.

Et c’est peut-être pour cette raison que la plupart des réponses ont été renvoyées au style et à la syntaxe personnels.

0
Ruz

Il y a 2 utilisations possibles du code php:

  1. Code PHP tel que définition de classe ou définition de fonction
  2. Utilisez PHP comme langage de template (c'est-à-dire dans les vues)

dans le cas 1. la balise de fermeture est totalement inutile, j'aimerais aussi voir seulement une (une) balise ouverte php et une balise de fermeture NO (zéro) dans un tel cas. C'est une bonne pratique car cela permet au code d'être propre et de séparer la logique de la présentation. Pour le cas de présentation (2.), certains ont trouvé naturel de fermer toutes les balises (même celles traitées en PHP), ce qui conduit à une confusion, car le PHP a en fait 2 cas d'utilisation distincts, ce qui ne devrait pas être mixte: logique/calcul et présentation

0
Daniele Cruciani