Почему бы опустить закрывающий тег?

308

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

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

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

  • 3
    возможный дубликат [почему в некоторых скриптах они пропускают закрывающий тег php?>] ( stackoverflow.com/questions/3219383/… )
  • 0
    @Christian - Вы имеете в виду, что использование output_buffering является ленивым или отключение ?> Ленивым?
Показать ещё 7 комментариев
Теги:
security
http-headers

14 ответов

299
Лучший ответ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 2
    > любой программист с полусмысленностью может помнить, чтобы не добавлять лишние пробелы. Более того, любой разработчик, имеющий половину ума, может добавить хук до фиксации в SVC, чтобы автоматически удалять любые конечные пробелы: без суеты и суеты.
  • 6
    @BryanH, пока у вас нет файла, где конечный пробел абсолютно необходим, но это очень редко.
Показать ещё 4 комментария
48

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

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

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

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

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

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

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

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

Изменение тегов тегов

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

  • Он содержит еще несколько воплощений из-за магии PHP новой строки:

    ? > \n (Unix linefeed)

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

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

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

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

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

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

    __HALT_COMPILER();
    ?>
    

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

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

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

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

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

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

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

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

phptags tag tidier
Изображение 727
https://fossil.include-once.org/phptags/

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

  • phptags --warn --whitespace *.php

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

  • 2
    Примечание для себя: тупая фраза привлекает анонимных голосов.
  • 6
    Да, тупые и провокационные фразы привлекают негативные голоса. Из того, что я прочитал в течение долгого времени, отсутствие маркера закрытия не имеет абсолютно никаких недостатков, если вы не работаете с программным обеспечением, которое не может справиться с этим. Если вы на самом деле не можете доказать, что пропуск закрывающих токенов - это плохо и очень нудно, мой понижающий голос остается;)
Показать ещё 6 комментариев
15

Это не тег...

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

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

  • 10
    Если это не тег, что это?
  • 0
    Можете ли вы привести пример? Может быть, мой конфиг php ненормальный, но я не могу воспроизвести проблему.
Показать ещё 9 комментариев
12

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

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

будет.

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

  • 4
    Как это делает вас безопасным? Это просто ленивый способ исправить плохой код ...
  • 3
    Вот почему я выделил курсивом. Он предотвращает ошибки, которые могут стоить вам много времени из-за нежелательного места после ?> . безопасность не может быть хорошим словом здесь. В любом случае, это ничего не исправляет (для меня это не плохой код, чтобы предотвратить вещи, echo здесь было бы плохим кодом), но / и это все еще действует. Докажите, что я не прав в этом.
Показать ещё 6 комментариев
10

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

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

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

  • 2
    Спасибо за короткий ответ!
8

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

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

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

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

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

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

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

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

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

  • 1
    Это совершенно неверно. PHP НЕ переводит эти теги в XML, и, следовательно, дисбаланс не генерируется.
  • 7
    @Felicitus: Полагаю, вы пропустили ту часть, которая гласит: «Я не говорю, что это важно. Это просто мнение, которое я не вижу выраженным слишком часто, так что где лучше поделиться им ...» Это не о PHP перевод тегов в XML. Речь идет о том, что происходит, когда файл интерпретируется в контексте XML (например, HTML или редакторы и т. Д.) ... Но точка упущена ...
6

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

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

Вот ошибка, которую генерирует Apache:

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

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

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

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

  • 22
    Этот тег, «никогда не разрешенный», вероятно, является стандартом кодирования Zend, но это не правило синтаксиса для форматирования файлов PHP.
4

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

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

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

Pros

Против

Заключение

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

1

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

  • С полным инструкцией по обработке Синтаксис (<?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 (возможно, был открыт IP-адрес <?php или нет). Жизнь проще, если вы постоянно оставляете свои документы в режиме игнорирования PHP. Это похоже на работу с хорошо отформатированными HTML-документами по сравнению с документами с незакрытыми, плохо вложенными тегами и т.д.

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

0

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

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

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

0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню