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

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

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

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

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

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

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

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

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

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

Бонус: несколько gotchas (фактически в настоящее время один), связанных с этими двумя символами:

  1. Даже некоторые известные библиотеки могут содержать избыточные окончания строки после ?> . Примером является Smarty, даже самые последние версии обеих ветвей 2. * и 3. * имеют это. Поэтому, как всегда, смотрите на сторонний код . Бонус в бонусе: регулярное выражение для удаления ненужных завершений PHP: замените (\s*\?>\s*)$ пустым текстом во всех файлах, содержащих PHP-код.

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

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

Так что для вашего вопроса:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Регулярно ? > close tag также известен как T_CLOSE_TAG или, таким образом, «close token».

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

    ? > \ n (Unix linefeed)

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

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

    Однако PHP не поддерживает Unicode combo linebreak NEL (U + 0085).

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

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

  • « Трудный тег тега » даже не один – просто сделал этот термин для аналогии. Однако __halt_compiler должен распознаваться как близкий токен.

     __HALT_COMPILER(); ?> 

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

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

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

    • Простой интервал // ? > // ? > для предотвращения обнаружения с помощью токенизатора PHP.

    • Или причудливые заменители Unicode // ﹖﹥ (U + FE56 SMALL QUESTION MARK, U + FE65 SMALL ANGLE BRACKET), которые может использовать регулярное выражение.

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

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

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

Значок тегов phptags

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

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

  • phptags --warn --whitespace *.php

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

Это не тег …

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

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

Очень полезно не закрывать ?> .

Файл остается действительным для 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 ); 

будем.

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

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

  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-кода внутри …

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

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

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

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

http://php.net/manual/en/language.basic-syntax.phptags.php

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

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

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

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

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

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

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

Pros

  • Было бы логично закрыть любой открытый тег , как на других языках. Не только теги X (HT) ML, но также фигурные скобки, скобки …
  • Менее запутанный для начинающих .

Cons

  • Избегает головной боли с добавлением непреднамеренных пробелов после закрывающего тега, поскольку это нарушает поведение функции header () … Известно, что некоторые редакторы или FTP-клиенты / серверы автоматически меняют конец файлов (по крайней мере, это их конфигурация по умолчанию)
  • Руководство PHP говорит, что закрывающий тег является необязательным , и Zend даже запрещает его .

Вывод

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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