Почему бы опустить закрывающий тег? - PullRequest
355 голосов
/ 10 декабря 2010

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

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

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

Ответы [ 14 ]

308 голосов
/ 21 декабря 2010

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

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

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

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

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

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

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

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

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

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

Итак, на ваш вопрос:

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

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

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

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

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

55 голосов
/ 17 декабря 2010

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

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

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

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

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

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

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

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

Варианты закрытия тегов

  • обычный ? > тег закрытия также известен как T_CLOSE_TAG или, таким образом, «токен закрытия».

  • Itвключает в себя еще несколько воплощений, из-за того, что PHP * magic newline eat :

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

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

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

    PHP не поддерживает разрыв строки комбо Unicode NEL (U + 0085).

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

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

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

    __HALT_COMPILER();
    ?>
    

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

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

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

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

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

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

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

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

Tidier тега phptags
image
https://fossil.include -once.org / phptags /

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

  • phptags --warn --whitespace *.php

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

21 голосов
/ 10 декабря 2010

Это не тег…

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

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

15 голосов
/ 10 декабря 2010

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

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

воля.

На этот раз вам нужно быть ленивым, чтобы быть защищенным .

13 голосов
/ 22 августа 2016

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

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

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

9 голосов
/ 15 декабря 2010

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

  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 голосов
/ 10 декабря 2010

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

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

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

7 голосов
/ 09 июня 2014

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

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

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

[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)
6 голосов
/ 28 февраля 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...