Зачем опускать тег закрытия?


Я продолжаю читать, что использовать тег закрытия PHP ?> в конце файла - плохая практика. Проблема заголовка кажется неуместной в следующем контексте (и это пока единственный хороший аргумент):

Современные версии PHP устанавливают флаг output_buffering в php.ini Если буферизация вывода включена, вы можете установить заголовки HTTP и файлы cookie после вывода html, поскольку возвращаемый код не отправляется в браузер немедленно.

Каждая книга по хорошей практике и вики начинается с этого "правила", но никто не предлагает веских причин. Есть ли еще одна веская причина пропустить конечный тег php?

Author: Paracetamol, 2010-12-10

14 answers

Хотя я не могу вспомнить никакой другой причины, отправка заголовков раньше, чем обычно, может иметь далеко идущие последствия. Ниже приведены лишь некоторые из них, которые пришли мне в голову в данный момент:

  1. В то время как в текущих версиях PHP может быть включена буферизация вывода, фактические производственные серверы, на которых вы будете развертывать свой код, гораздо важнее, чем любые машины разработки или тестирования. И они не всегда следуют последним тенденциям PHP немедленно.

  2. У вас могут быть головные боли из-за необъяснимой потери функциональности . Допустим, вы внедряете какой-то платежный шлюз и перенаправляете пользователя на определенный URL-адрес после успешного подтверждения обработчиком платежей. Если произойдет какая-либо ошибка PHP, даже предупреждение или избыточное окончание строки, платеж может остаться необработанным, и пользователь все еще может показаться неоплаченным. Это также одна из причин, по которой ненужное перенаправление является злом, и если перенаправление должно использоваться, его следует использовать с осторожностью.

  3. В Internet Explorer могут возникать ошибки типа "Загрузка страницы отменена", даже в самых последних версиях. Это связано с тем, что AJAX ответ/json include содержит что-то, чего он не должен содержать, из-за избыточных окончаний строк в некоторых файлах PHP, с чем я столкнулся несколько дней назад.

  4. Если у вас есть некоторые загрузки файлов в вашем приложении, они тоже могут сломаться из-за этого. И вы можете этого не заметить, даже спустя годы, поскольку специфическая привычка к загрузке зависит от сервера, браузера, типа и содержимого файла (и, возможно, некоторых других факторов, с которыми я не хочу вас утомлять).

  5. Наконец, многие фреймворки PHP, включая Symfony, Zend и Laravel (об этом нет упоминания в руководстве по кодированию , но оно соответствует требованиям) и стандарт PSR-2 (пункт 2.2) требуют пропуска закрывающего тега. Руководство по PHP сам по себе (1,2), Wordpress, Drupal и многие другие PHP-программы, я думаю, советуют это сделать. Если у вас просто войдет в привычку следовать стандарту (и настроить PHP-CS-Fixer для вашего кода), вы можете забыть об этой проблеме. В противном случае вам всегда нужно будет держать этот вопрос в уме.

Бонус: несколько ошибок (на самом деле в настоящее время одна), связанных с этими 2 персонажами:

  1. Даже некоторые известные библиотеки могут содержать лишнюю строку окончания после ?>. Примером может служить Smarty, даже в самых последних версиях ветвей 2.* и 3.* это есть. Поэтому, как всегда, следите за кодом третьей стороны. Бонус в бонусе: Регулярное выражение для удаления ненужных окончаний PHP: замените (\s*\?>\s*)$ пустым текстом во всех файлах, содержащих код PHP.
 290
Author: Halil Özgür, 2014-07-10 12:17:55

Причина, по которой вы должны оставить закрывающий тег php (?>), заключается в том, чтобы программист случайно не отправил дополнительные символы новой строки.

Причина, по которой вы не должны оставлять закрывающий тег php, заключается в том, что он вызывает дисбаланс в тегах php, и любой программист с половиной ума может помнить, что не следует добавлять дополнительные пробелы.

Итак, что касается вашего вопроса:

Есть ли еще одна веская причина пропустить конечный тег php?

Нет, нет еще одна веская причина пропустить окончательные теги php.

Я закончу некоторыми аргументами в пользу того, чтобы не беспокоиться о закрывающем теге:

  1. Люди всегда способны ошибаться, какими бы умными они ни были. Придерживаться практики, которая уменьшает количество возможных ошибок, - это (ИМХО) хорошая идея.

  2. PHP - это не XML. PHP не должен придерживаться строгих стандартов XMLs, чтобы быть хорошо написанным и функциональным. Если отсутствующий закрывающий тег вас раздражает, вам разрешено использовать закрывающий тег, это не является непреложным правилом, так или иначе.

 112
Author: zzzzBov, 2010-12-15 19:09:41

Это рекомендация по стилю кодирования для новичков , исполненная благих намерений и рекомендованная руководством.

  • Однако отказ от ?> решает только небольшую часть общих заголовков, уже отправленных, вызывает (необработанный вывод, Спецификация , уведомления и т. Д.) И их последующие проблемы.

  • PHP на самом деле содержит некоторую магию, позволяющую уничтожать одиночные разрывы строк после закрывающего токена ?>. Хотя это имеет историческую выпускает, и оставляет новичков все еще подверженными ошибочным редакторам и неосознанному перетасовыванию других пробелов после ?>.

  • Стилистически некоторые разработчики предпочитают рассматривать <?php и ?> как инструкции по обработке тегов SGML/XML, подразумевая согласованность баланса завершающего маркера закрытия. (Который, кстати, полезен для класса объединения зависимостей, включает в себя замену неэффективной автоматической загрузки файла за файлом.)

  • Несколько необычно, что открытие <?php характеризуется как PHPSshebang (и полностью выполнимо для binfmt_misc), тем самым подтверждая избыточность соответствующего закрывающего тега.

  • Существует очевидное несоответствие между классическими руководствами по синтаксису PHP, предписывающими ?>\n, и более недавними (PSR-2), согласующимися с пропуском.
    (Для справки: структура Zend, постулирующая одно над другим, не подразумевает присущего ей превосходства. Это неправильное представление что эксперты были привлечены к/целевой аудитории громоздких API).

  • SCMS и современные IDE предоставляют встроенные решения, в основном облегчающие уход за близкими тегами.

Отказ от любого использования тега ?> close просто задерживает объяснение базового поведения обработки PHP и семантики языка, чтобы избежать нечастых проблем. Это практично по-прежнему для совместной разработки программного обеспечения из-за различий в уровне владения участники.

Закрыть варианты тегов

  • Обычный ?> закрывающий тег также известен как T_CLOSE_TAG, или, таким образом, "закрыть токен".

  • Он включает в себя еще несколько воплощений, из-за магии PHPs поедание новой строки:

    ?>\ n ( Перевод строки Unix)

    ?>\ r ( Возврат каретки, классический MACs)

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

    PHP не поддерживает комбинированный разрыв строки в Юникоде НЕЛ ( U+0085), однако.

    Ранние версии PHP имели компиляторы IIRC, несколько ограничивающие агностицизм платформы (FI даже просто использовал > в качестве маркера близости), что, вероятно, является историческим происхождением избегания закрытых тегов.

  • Часто упускается из виду, но до PHP7 удаляет их, обычный <?php открывающий токен может быть действительным в паре с редко используемым </script> как нечетный закрывающий знак.

  • " жесткий тег закрытия" даже не один - просто придумал этот термин для аналогии. Концептуально и с точки зрения использования __halt_compiler однако должен быть распознан как маркер близости.

    __HALT_COMPILER();
    ?>
    

    , в котором в основном токенизатор отбрасывает любой код или простые разделы HTML после этого. В определенные заглушки PHAR используют это или его избыточную комбинацию с ?>, как показано на рисунке.

  • Аналогично делает пустым return; нечасто заменяйте сценарии включения, делая любые ?> с конечными пробелами неэффективными.

  • Затем существуют всевозможные мягкие/искусственные варианты закрывающих тегов; менее известные и редко используемые, но обычно для закомментированных токенов:

    • Простой интервал // ? > чтобы избежать обнаружения токенизатором PHPS.

    • Или необычные заменители Юникода // ﹖﹥ ( U+FE56 МАЛЕНЬКИЙ ВОПРОСИТЕЛЬНЫЙ ЗНАК, U+FE65 МАЛЕНЬКАЯ УГЛОВАЯ СКОБКА), которую может понять регулярное выражение.

    Оба ничего не значат для PHP, но могут иметь практическое применение для неосведомленных или полуосознанных внешних наборов инструментов PHP. Снова cat - на ум приходят объединенные сценарии с результирующими // ? > <?php конкатенациями, которые встроены - сохраняют прежний файл разделение.

Таким образом, существуют контекстно-зависимые, но практические альтернативы императивному пропуску закрывающего тега.

Ручная настройка ?> закрывающих тегов в любом случае не очень современна. Для этого всегда существовали инструменты автоматизации (даже если это были только sed/awk или регулярные выражения). В частности:

Теги Phptags более аккуратные

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

Который мог бы обычно используется для --unclose тегов php для стороннего кода или, скорее, просто исправляет любые (и все) фактические проблемы с пробелами/спецификациями:

  • phptags --warn --whitespace *.php

Он также обрабатывает --long преобразование тегов и т.д. для совместимости среды выполнения/конфигурации.

 51
Author: mario, 2017-05-23 12:34:48

Это не тег...

Но если он у вас есть, вы рискуете получить пробел после него.

Если вы затем используете его в качестве включения в верхней части документа, вы можете в конечном итоге вставить пробелы (т. Е. Содержимое) перед попыткой отправки HTTP-заголовков... что запрещено.

 16
Author: Quentin, 2010-12-10 16:02:45

Довольно полезно не допускать закрытия ?>.

Файл остается действительным для PHP (не синтаксическая ошибка), и, как сказал @David Dorward, он позволяет избежать пробелов/разрывов (всего, что может отправить заголовок в браузер) после ?>.

Например,

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

Не будет действительным.

Но

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

Будет.

На этот раз вы должны быть ленивы, чтобы быть в безопасности.

 12
Author: Shikiryu, 2014-07-19 15:46:40

Согласно документам , предпочтительнее опустить закрывающий тег, если он находится в конце файла по следующей причине:

Если файл представляет собой чистый PHP-код, предпочтительно опустить закрывающий тег PHP в конце файла. Это предотвращает случайное добавление пробелов или новых строк после закрывающего тега PHP, что может вызвать нежелательные эффекты, поскольку PHP начнет буферизацию вывода, когда программист не намерен отправлять какие-либо выходные данные в этот момент в сценарии.

Руководство по PHP > Справочник по языку > Базовый синтаксис > Теги PHP

 10
Author: Asaph, 2018-03-17 19:39:51

Ну, есть два способа взглянуть на это.

  1. PHP-код - это не что иное, как набор инструкций по обработке XML, и поэтому любой файл с расширением .php - это не что иное, как XML-файл, который просто случайно анализируется для PHP-кода.
  2. PHP просто так получилось, что он использует формат инструкций по обработке XML для своих тегов открытия и закрытия. Исходя из этого, файлы с расширениями .php МОГУТ быть допустимыми XML-файлами, но им не нужно быть.

Если вы верите первому маршруту, то все PHP-файлы требуют закрывающих конечных тегов. Если их опустить, будет создан недопустимый XML-файл. С другой стороны, без объявления открытия <?xml version="1.0" charset="latin-1" ?> у вас все равно не будет действительного XML-файла... Так что это не главная проблема...

Если вы верите второму маршруту, который открывает дверь для двух типов файлов .php:

  • Файлы, содержащие только код (например, библиотечные файлы)
  • Файлы, содержащие собственный XML, а также код (например, файлы шаблонов)

Исходя из этого, файлы только с кодом могут заканчиваться без закрывающего тега ?>. Но файлы XML-кода не подходят для завершения без закрытия ?>, так как это приведет к недействительности XML.

Но я знаю, о чем ты думаешь. Вы думаете, какое это имеет значение, вы никогда не будете отображать PHP-файл напрямую, так что кого волнует, является ли он допустимым XML. Ну, это имеет значение, если вы разрабатываете шаблон. Если это допустимый XML/HTML, обычный браузер просто не будет отобразите PHP-код (он рассматривается как комментарий). Таким образом, вы можете создать макет шаблона без необходимости запускать PHP-код в...

Я не говорю, что это важно. Это просто мнение, которое я не вижу выраженным слишком часто, так что где лучше поделиться им...

Лично я не закрываю теги в файлах библиотеки, но делаю это в файлах шаблонов... Я думаю, что это личное предпочтение (и руководство по кодированию), основанное больше всего на чем-либо сложном...

 8
Author: ircmaxell, 2014-07-19 15:49:40

Ну, я знаю причину, но не могу ее показать:

Для файлов, содержащих только PHP-код, закрывающий тег (?>) никогда не разрешается. Это не требуется PHP, и его отсутствие предотвращает случайное добавление завершающего пробела в ответ.

Источник: http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html

 6
Author: tawfekov, 2014-07-19 15:45:04

В дополнение ко всему, что уже было сказано, я собираюсь привести еще одну причину, по которой нам было очень трудно отлаживать.

Apache 2.4.6 с PHP 5.4 на самом деле ошибки сегментации на наших производственных машинах, когда за закрывающим тегом php остается пустое пространство. Я просто потратил впустую часы, пока, наконец, не сузил круг поиска ошибки с помощью strace.

Вот ошибка, которую выдает Apache:

[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)
 6
Author: Artem Russakovskii, 2014-07-19 21:12:16

Плюсы

Минусы

Заключение

Я бы сказал, что аргументы в пользу исключения тега выглядят более убедительными (помогает избежать большой головной боли с заголовком () + это "рекомендация" PHP/Zend). Я признаю, что это не самое "красивое" решение, которое я когда-либо видел с точки зрения синтаксической согласованности, но что может быть лучше?

 4
Author: Frosty Z, 2013-03-19 08:57:16

"Есть ли другая веская причина (кроме проблемы с заголовком) пропустить конечный тег php?"

Вы не хотите случайно выводить посторонние символы пробелов при создании двоичного вывода, CSV данных или других выходных данных, отличных от HTML.

 4
Author: user1238364, 2014-07-19 21:10:48

Поскольку мой вопрос был помечен как дубликат этого, я думаю, что это нормально, чтобы опубликовать, почему НЕ по некоторым причинам может быть желательно опустить закрывающий тег ?>.

  • С полным синтаксисом Инструкций по Обработке (<?php ... ?>) PHP-источник является действительным документом SGML, который может быть проанализирован и обработан без проблем с помощью анализатора SGML. С дополнительными ограничениями он также может быть допустимым XML/XHTML.

Ничто не мешает вам писать допустимый код XML/HTML/SGML. PHP документация знает об этом. Выдержка:

Примечание: Также обратите внимание, что если вы внедряете PHP в XML или XHTML, вам нужно будет использовать теги , чтобы соответствовать стандартам.

Конечно, синтаксис PHP не является строгим SGML/XML/HTML, и вы создаете документ, который не является SGML/XML/HTML, точно так же, как вы можете превратить HTML в XHTML, чтобы быть совместимым с XML или нет.

  • В какой-то момент вам может потребоваться объединить источники. Это будет не так легко, как просто сделать cat source1.php source2.php, если у вас есть несоответствие, вызванное пропуском закрывающих тегов ?>.

  • Без ?> сложнее определить, был ли документ оставлен в режиме PHP escape или в режиме PHP ignore (возможно, тег PI <?php был открыт или нет). Жизнь становится проще, если вы постоянно оставляете свои документы в режиме игнорирования PHP. Это похоже на работу с хорошо отформатированными HTML-документами по сравнению с документами с незакрытыми, плохо вложенными тегами и т.Д.

  • Похоже, что некоторые редакторы как у Dreamweaver могут быть проблемы с PI, оставленным открытым [1].

 1
Author: doc, 2014-07-08 18:01:28

Если я правильно понимаю вопрос, это связано с буферизацией вывода и влиянием, которое это может оказать на закрывающие/завершающие теги. Я не уверен, что это вполне обоснованный вопрос. Проблема в том, что выходной буфер не означает, что все содержимое хранится в памяти перед отправкой клиенту. Это означает, что часть контента есть.

Программист может намеренно очистить буфер или выходной буфер, так что опция выходного буфера в PHP действительно меняет способ закрытия тег влияет на кодирование? Я бы сказал, что это не так.

И, возможно, именно поэтому большинство ответов вернулось к личному стилю и синтаксису.

 0
Author: Ruz, 2010-12-17 17:07:39

Существует 2 возможных варианта использования php-кода:

  1. PHP-код, такой как определение класса или определение функции
  2. Используйте PHP в качестве языка шаблонов (т.е. в представлениях)

В случае 1. закрывающий тег совершенно не подходит, также я хотел бы видеть только 1 (один) открытый тег php и НИ одного (нулевого) закрывающего тега в таком случае. Это хорошая практика, поскольку она делает код чистым и отделяет логику от представления. Для случая презентации (2.) некоторые сочли естественным закрыть все теги (даже обработанные PHP), что приводит к путанице, так как PHP фактически имеет 2 отдельных варианта использования, которые не следует смешивать: логика/исчисление и представление

 0
Author: Daniele Cruciani, 2015-12-31 11:47:52