なぜ終了タグを省略するのですか?


374

?>ファイルの最後にPHPの終了タグを使用することはお勧めできません。ヘッダーの問題は、次のコンテキストでは無関係であるように見えます(これは、これまでのところ唯一の良い議論です):

最新バージョンのPHPでは、php.iniにoutput_bufferingフラグが設定されています。出力バッファリングが有効になっている場合、返されたコードはすぐにはブラウザーに送信されないため、HTMLの出力後にHTTPヘッダーとCookieを設定できます。

すべての優れた実践書とwikiはこの「ルール」で始まりますが、誰も正当な理由を提供しません。 終了PHPタグをスキップする別の理由はありますか?


3
[一部のスクリプトでphpの終了タグが省略されている理由>>](stackoverflow.com/questions/3219383/…)の重複の可能性
Gordon

@Christian-output_bufferingを使用するのが面倒?>だと思いますか、それとも無視するのが面倒です?
El Yobo

4
@Gordon-私はそれが重複しているとは思わない、OPは表面的な理由を知っている、それが出力バッファリングで完全に解決されたかどうかを知りたいだけだ。
El Yobo

5
より良い質問は次のとおりです:なぜ閉じるタグを含めるのですか?コードは悪です。最良のコードはコードがまったくないことです。コードで解決する代わりに問題を排除できる場合、これはコードよりも優れています。この場合、解決する必要のある問題はありません。コードは終了タグがなくても正常に機能します。
still_dreaming_1 2015

19
ああ、これはタブ対スペースの聖戦の場所ではありません、笑:)
Kevin Wheeler

回答:


322

通常のコースよりも早くヘッダーを送信すると、広範囲に影響が及ぶ可能性があります。以下は、たまたま私の頭に浮かんだもののほんの一部です。

  1. 現在のPHPリリースでは出力バッファリングがオンになっている場合がありますが、コードをデプロイする実際の本番サーバーは、開発マシンやテストマシンよりもはるかに重要です。そして、常に最新のPHPトレンドをすぐにフォローする傾向があるわけではありません。

  2. 不可解な機能の喪失に頭が痛くなるかもしれません。たとえば、ある種の支払いゲートウェイを実装していて、支払い処理業者による確認が成功した後、ユーザーを特定のURLにリダイレクトするとします。なんらかのPHPエラー、警告、または過剰な行末が発生した場合、支払いは未処理のままになり、ユーザーは未請求のように見えることがあります。これは、不必要なリダイレクトが悪用される理由の1つでもあり、リダイレクトを使用する場合は、注意して使用する必要があります。

  3. 最新バージョンでも、Internet Explorerで「ページの読み込みがキャンセルされました」タイプのエラーが発生する場合があります。これは、AJAX応答/ jsonインクルードに含まれてはならないものが含まれているためです。これは、数日前に発生したのと同じように、一部のPHPファイルの行末が多すぎるためです。

  4. アプリにいくつかのファイルのダウンロードがある場合、これが原因でファイルが破損する可能性もあります。そして、ダウンロードの特定の習慣がサーバー、ブラウザー、ファイルの種類と内容(そしておそらく私が退屈させたくない他のいくつかの要因)に依存するため、数年経っても気付かないかもしれません。 。

  5. 最後に、SymfonyZend、Laravel を含む多くのPHPフレームワーク(コーディングガイドラインではこれについての言及はありませんが、スーツに従います)およびPSR-2標準(項目2.2)では、終了タグの省略が必要です。PHPマニュアル自体(12)、WordpressのDrupalの私は推測する他の多くのPHPソフトウェア、そうすることをお勧めします。標準に従う(そしてコードにPHP-CS-Fixerを設定する)だけの習慣をつければ、問題を忘れることができます。それ以外の場合は、常に問題を心に留めておく必要があります。

ボーナス:これらの2つのキャラクターに関連するいくつかの落とし穴(実際には現在1つ):

  1. 一部の有名なライブラリでも、の後に余分な行末が含まれる場合があります?>。例はSmartyです。2。*と3. *ブランチの両方の最新バージョンにもこれがあります。そのため、いつものように、サードパーティのコードに注意してください。おまけのボーナス:不要なPHPの末尾を削除するための正規表現:(\s*\?>\s*)$PHPコードを含むすべてのファイルで空のテキストに置き換えます。

検索と置換ダイアログで、Netbeans IDEでタグを見つけるために使用した少し異なる正規表現:\?>(?s:.){0,10}\Z 簡単な説明:changeset.hr/blog/miscellaneous/catch-near-eof-with-regex
frnhr

@Cek、その後に10文字以下の任意のテキスト(コードを含む)をキャッチします?>。たとえば、一致し、削除さ?> Hello<?php echo "test"; ?> Helloます。クローズタグのみをクリアしたいと思います。
HalilÖzgür2013年

6
さらに悪いことに、Apache 2.4.6とPHP 5.4では、終了タグの後ろに空きスペースがあると、実稼働マシンで実際にseg障害が発生します。straceでバグを最終的に絞り込むまで、私は何時間も無駄にしただけです。Apacheがスローするエラーは次のとおり[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)です。
Artem Russakovskii 14年

3
@INTPnerdああ、質問とほとんどの回答はヘッダーのことを指しているので、このスレッドを読んでいる人なら誰でも知っていると思います。ここでの回答の多くにおける根本的な問題と問題の実際の原因は、の後の不要な空白です?>。これにより、(他の出力と同様に)ヘッダーが出力と同時に送信されます。「HTMLヘッダー」はありません(無関係のHTML5 <header>タグを除きます)。
HalilÖzgür、2015

2
これは、グローバル修飾子に関係なく機能するはずです。\ s * \?> \ s * \ Z末尾の「\ Z」に注意してください。ファイルの最後の空白以外の最後の場合にのみ、php終了タグを確実にキャプチャします。
Erutan409 2015

122

phpの終了タグ(?>)を省略すべき理由は、プログラマが誤って余分な改行文字を送信しないようにするためです。

phpの終了タグを省略してはならない理由は、phpのタグに不均衡が生じるためであり、頭が半分のプログラマは余計な空白を追加しないことを覚えているからです。

だからあなたの質問のために:

終了phpタグをスキップする別の理由はありますか?

いいえ、phpの終了タグをスキップする別の理由はありません。

終了タグを気にしないためのいくつかの引数で終了します。

  1. どんなに賢くても、人はいつでも間違いを犯すことができます。可能性のある間違いの数を減らす習慣を守ることは(私見)良い考えです。

  2. PHPはXMLではありません。PHPは、適切に記述され機能するために、XMLの厳密な標準に準拠する必要はありません。欠落している終了タグが気になる場合は、終了タグを使用することができます。これは、いずれにしても根本的なルールではありません。


2
> 頭が半分のプログラマは、余計な空白を追加しないことを忘れないでください。さらに良いことに、1/2のマインドを持った開発者であれば、コミット前のフックをSVCに追加して、末尾のスペースが自動的に削除されるようにすることができます。
BryanH

6
@BryanH、最後の空白が絶対に必要なファイルができるまで、それは非常にまれです。
zzzzBov 2013年

1
もちろんそうです。いくつかの非常にクールな代替案については、マリオの答えをチェックしてください。
BryanH 2013年

>「phpの終了タグを省略すべきではない理由は、phpのタグに不均衡が生じるためであり、頭が半分のプログラマは余計な空白を追加しないことを覚えているからです。」Windowsでは、たぶん。UNIXライクなシステムでは、すべてのファイルが\ nで終わり、プログラムによって追加されます。 編集:ああ!以下で@marioが述べているように、PHPは実際にそれを食べます。
Andrea

2
さらに重要なのは、3倍の3倍の心を持つプログラマでさえ人間であり、何かを忘れているということです。
セバスチャンマッハ

57

これは初心者向けのコーディングスタイルの推奨事項であり、意図がよく、マニュアルで推奨されています

  • ?>ただし Eschewing は、すでに送信された一般的なヘッダーのトリクル(生の出力、BOM、通知など)とそれらのフォローアップ問題を解決します。

  • PHPには、実際には、?>クローズトークンの後に単一の改行を消す魔法が含まれています。とはいえ、これには歴史的な問題があり、新参者はまだフレークなエディターの影響を受けやすく、その後他の空白を無意識のうちにシャッフルします?>

  • 文体的には、一部の開発者はSGMLタグ/ XML処理命令として表示<?php?>、末尾のクローズトークンのバランスの一貫性を示唆しています。(どちらが、非効率的なファイルごとのオートローディングに取って代わる依存関係結合クラスインクルードに役立ちます。)

  • 少し珍しいことに、オープニング<?phpPHPのシバン(およびbinfmt_miscごとに完全に実現可能)として特徴付けられ、それによって対応する終了タグの冗長性が検証されます。

  • 古典的なPHP構文ガイドの義務化?>\nと省略について同意した最近のPHP構文ガイド(PSR-2)の間には、明らかにアドバイスの不一致があります
    (記録のために:Zend Frameworkを重ねて仮定することは、その固有の優位性を意味するものではありません。エキスパートが扱いにくいAPIの対象ユーザー/対象ユーザーに引き付けられたというのは誤解です)。

  • SCMと最新のIDEはタグのクローズ処理を軽減する組み込みソリューションを提供します

?>closeタグの使用を思いとどまらせても、PHPの基本的な処理動作と言語のセマンティクスの説明が遅れて、まれな問題が回避されるだけです。参加者の習熟度のばらつきにより、協調的なソフトウェア開発にはまだ実用的です。

タグのバリエーションを閉じる

  • 通常の ?>終了タグとしても知られているT_CLOSE_TAG、またはこれ「クローズトークン」。

  • PHPの魔法の改行を食べるため、それはさらにいくつかの化身で構成されています

    ?>\n (UNIX改行)

    ?>\r (キャリッジリターン、クラシックMAC)

    ?>\r\n (DOS / WinではCR / LF)

    NELただし、PHPはUnicodeコンボ改行(U + 0085)をサポートしていません。

    初期のPHPバージョンにはIIRCコンパイルインがあり、プラットフォームにとらわれないことがある程度制限さ>れていました(FI は終了マーカーとしても使用されています)。これは終了タグ回避の歴史的な起源である可能性があります。

  • 見過ごされがちですが、PHP7で削除されるまで、通常の<?php開始トークンは、めったに使用されない奇妙な終了トークン有効に組み合わせることができます</script>

  • ハードクローズタグ」は1つではありません。その用語を類推のために作成しただけです。__halt_compilerただし、概念的にも使用方法も、クローズトークンとして認識される必要があります。

    __HALT_COMPILER();
    ?>

    基本的に、トークナイザーはその後コードやプレーンHTMLセクションを破棄します。特に、PHARスタブは、それを使用するか、または図のようにその冗長な組み合わせを使用?>します。

  • 同様に、インクルードスクリプトでvoidがreturn;頻繁に置換されず?>、末尾の空白があるものは無効になります

  • 次に、あらゆる種類のソフト/フェイク終了タグのバリエーションがあります。あまり知られていないがめったに使用されないが、通常はコメントアウトされたトークンごとに:

    • // ? >PHPトークナイザーによる検出を回避するための単純な間隔。

    • または// ﹖﹥、正規表現が把握できる豪華なUnicode置換(U + FE56 SMALL QUESTION MARK、U + FE65 SMALL ANGLE BRACKET)。

    どちらもPHPに意味がありませんが、PHP非対応または準対応の外部ツールキットの実用的な用途があります。ここでも、cat結合されたスクリプトが頭に浮かび、結果として// ? > <?php、以前のファイルセクションをインライン保持する連結が生成されます。

したがって、必須の終了タグの省略には、コンテキストに依存しますが実用的な代替手段があります。

?>どちらかの方法で閉じるタグを手動でベビーシッターすることは、非常に現代的ではありません。そのための自動化ツールは常に存在します(sed / awkやregex-onelinersであっても)。特に:

phptagsタグtidier

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

これは通常--unclose、サードパーティのコードのphpタグに使用できますが、実際の空白/ BOMの問題を修正するだけです。

  • phptags --warn --whitespace *.php

また--long、ランタイム/構成の互換性のためにタグ変換なども処理します。


7
はい、率直で挑発的な表現は賛成票を集めます。私が時間をかけて読んだことから、クロージングトークンを除外することには、それを処理できないソフトウェアを使用しない限り、まったくマイナス面がありません。クローズトークンを省略することが悪いことであり、非常に初心者がすべきことを実際に証明できない限り、私の反対票は残ります;)
jpeltoniemi

2
@Pichan:許可します。しかし、私はあなたがここで言われていることを完全に理解していないと思います。ゆがみと回避は、2つの異なるものです。そして、半分解決された問題は、ヘビ油のアドバイスの結果です。
マリオ

6
@mario:初心者向けのコーディングスタイルの推奨事項です。同意しません。Zend Framework全体で終了タグが省略されています。これは非常に個人的な選択だと思います。<?phpを開いたままにしておき、初心者は感じません:)
Daniele Vrut

1
HTMLはどうですか?それは必要ですか?たとえば<?php if($var): ?>Hello World<?php endif; ?>??? 特に言及されていないので、本当に興味があります。
WASasquatch、2015年

1
@WASasquatchはい。HTMLモードとPHPモードを切り替える場合は、どのような場合でもcloseトークンが必要になります。(ここでの元の質問には実際には関係ありません。)
mario '20

22

タグではない…

しかし、それがある場合は、その後に空白ができるリスクがあります。

その後、ドキュメントの上部にインクルードとして使用すると、HTTPヘッダーを送信しようとする前に空白(コンテンツ)が挿入される可能性があります。これは許可されていません。


10
タグではない場合、それは何ですか?
danidacar

例を挙げていただけますか?多分私のphp設定はwhackですが、問題を再現できません。
danidacar

2
file1.php:<?php $i = 1; ?> 次にfile2.php:<?php include 'file1.php'; header('Location: http://www.google.com');?>
Quentin

1
出力バッファリングにも欠点があります。サーバー上のメモリをより多く使用します(すべての出力は、出力されるまでRAMに保存する必要があるため、バッファリングせずにすぐに実行されます)。また、これまでよりも少し遅いです。これらのどちらもほとんどの場合問題にはなりませんが、とにかく私は怠惰なので、閉じタグをオフのままにしないのはなぜですか?私phpcsは、ファイルのすべての1つに終了タグが残されていることを確認するために使用し、出力バッファリングについて心配していません:)
El Yobo

1
@danip:PHP構成ファイルでoutput_bufferフラグを設定した場合、この問題を再現できませんでした。
Jichao

16

締めくくりに?>しないのはかなり便利です。

ファイルは(構文エラーではなく)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 );

意志。

一度に、あなたは安全であるために怠惰でなければなりません。


3
だから私はイタリック体で安全を確保した。それはあなたの後に不要なスペースのために多くの時間を費やす可能性のあるエラーからあなたを防ぎます?>ここで安全とは良い言葉ではないかもしれません。とにかく、それは何も修正しません(物事を防ぐのに私にとっては悪いコードではありません、echoここに悪いコードがあったでしょう)/そしてそれはまだ有効です。これについて私が間違っていることを証明してください。
四季竜

ところで、私はあなたに反対票を投じませんでした。しかし、私の意見はあなたの意見と互換性があります。それは何も修正しません。有効ではないとは言わなかったので、何も証明する必要はありません。
クリスチャン

1
Chouchenos、私はあなたが安全というよりは安全を意味しているに違いない。私見それのための否定は多すぎた。スクエアワンに戻しました。;-)結局、あなたは間違ったことを言っていませんでした。PHP開発ガイドラインでも、そうすることをお勧めします。たとえば、出力バッファリングよりも、終了タグの省略に依存する方が実際にははるかに優れています。後者は、display_errorsをオフに設定するようなものです。純粋な不正行為。そして、あなたのアプリがポータブルではなくなる可能性が高いです。原則として、出力バッファリングにまったく依存しない方が良いと私は本当に思います。
maraspin 2010

1
私は?>php onlyファイルの最後に置くのが好きな人に質問したくありません。しかし、末尾のスペースによって引き起こされるいくつかのエラーをデバッグする必要がありましたか?また、すべてのサーバーが同じように構成されているわけではなく、特に別のホストに移動した場合は、エラーの検出に非常に時間がかかります。そのままにしたい場合は?>、後続のスペースも追加し、チームがそれをデバッグする必要がある場合は、gitのせいにする準備ができています^^
CoffeDeveloper

16

docsによると次の理由でファイルの最後にある場合は、終了タグを省略することが推奨されます。

ファイルが純粋なPHPコードの場合は、ファイルの最後にあるPHP終了タグを省略することをお勧めします。これにより、PHP終了タグの後に偶然の空白や新しい行が追加されるのを防ぎます。プログラマーがスクリプトのその時点で出力を送信する意図がない場合、PHPは出力バッファリングを開始するため、望ましくない影響を引き起こす可能性があります。

PHPマニュアル>言語リファレンス>基本的な構文> PHPタグ


10

よく、私は理由を知っていますが、それを示すことはできません:

PHPコードのみを含むファイルの場合、終了タグ(?>)は許可されません。PHPでは必要ありません。これを省略すると、末尾の空白が誤って応答に挿入されるのを防ぎます。

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


23
そのタグが「決して許可されない」ことは、おそらくZendコーディング標準ですが、PHPファイル形式の構文規則ではありません。
Matt Huggins

9

まあ、それを見るには2つの方法があります。

  1. PHPコードはXML処理命令のセットにすぎないため、.php拡張子が付いたファイルは、たまたまPHPコード用に解析されるXMLファイルにすぎません。
  2. PHPは、たまたまその開始タグと終了タグのXML処理命令フォーマットを共有しています。それに基づいて、.php拡張子が付いたファイルは有効なXMLファイルである場合がありますが、そうである必要はありません。

最初のルートを信じる場合は、すべてのPHPファイルで終了タグを閉じる必要があります。それらを省略すると、無効なXMLファイルが作成されます。もう一度、opening <?xml version="1.0" charset="latin-1" ?>宣言がないと、とにかく有効なXMLファイルがありません...だから、それは大きな問題ではありません...

2番目のルートを信じるなら、それは2種類の.phpファイルへの扉を開きます:

  • コードのみを含むファイル(ライブラリファイルなど)
  • ネイティブXMLとコードを含むファイル(テンプレートファイルなど)

これに基づいて、コードのみのファイルは終了?>タグなしで終了しても問題ありません。ただし、XMLコードファイルは?>、XMLを無効にするため、終了せずに終了することはできません。

しかし、私はあなたが何を考えているか知っています。あなたはそれが何が重要かを考えています、あなたはPHPファイルを直接レンダリングするつもりはないので、それが有効なXMLであるかどうか誰が気にします。まあ、それはあなたがテンプレートを設計している場合重要です。有効なXML / HTMLの場合、通常のブラウザではPHPコードが表示されません(コメントのように扱われます)。そのため、PHPコードを実行せずにテンプレートをモックアウトできます...

これが重要だと言っているのではありません。あまり見かけない見方なので、共有した方がいいところ...

個人的には、ライブラリファイルのタグは閉じませんが、テンプレートファイルは閉じます...個人的な好み(およびコーディングガイドライン)は、何よりも難しいと思います...


1
これは完全に誤りです。PHPはこれらのタグをXMLに変換しないため、不均衡は生成されません。
Drachenkatze 2013年

7
@Felicitus:私はあなたが言う一部逃したと思います「私は、これが重要であるとは言わないよにそれは...私はそれを共有するので、何をより良い場所に、あまりにも頻繁に表現表示されていないことだけ眺めています。」これはPHPについてではありませんタグをXMLに変換します。これは、ファイルがXMLコンテキスト(HTMLやエディターなど)で解釈されるときに何が起こるかについてです...しかし、ポイントがありません...
ircmaxell 2013年

7

すでに述べたすべてのことに加えて、デバッグするのが非常に面倒だった別の理由を説明します。

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タグをスキップする理由は(ヘッダーの問題以外に)ほかにありますか?」

バイナリ出力、CSVデータ、または他のHTML以外の出力を生成するときに、不注意で不要なホワイトスペース文字を出力したくない場合。


1
最初に余分な空白行があったときにXMLパーサーが出力を拒否していたため、クライアントから文句がありました。さらに悪いことに、それは未修正の構成ファイルの終了タグの後に追加の行がある7つのうち1つのサーバーでのみ発生していました。
eswald

5

長所

短所

結論

私は、タグを省略したほうがよいように見えます(header()で大きな頭痛の種を避けるのに役立ちます+これはPHP / Zendの「推奨」です)。これは、構文の一貫性に関してこれまでに見た中で最も「美しい」ソリューションではないことを認めますが、何がより良いのでしょうか?


2

私の質問はこの質問の重複としてマークされていたので、何らかの理由で終了タグを省略しない?>ことがなぜ望ましいのかを投稿することは問題ないと思います。

  • 完全な処理命令構文(<?php ... ?>)を使用すると、PHPソースは有効なSGMLドキュメントであり、SGMLパーサーで問題なく解析および処理できます。追加の制限があれば、有効なXML / XHTMLにすることもできます。

有効なXML / HTML / SGMLコードの記述を妨げるものは何もありません。PHPのドキュメントはこれを認識しています。抜粋:

注:PHPをXMLまたはXHTMLに埋め込む場合は、標準に準拠するために<?php?>タグを使用する必要があることにも注意してください。

もちろん、PHP構文は厳密なSGML / XML / HTMLではなく、HTMLをXHTMLに変換してXMLに準拠させることができるのと同じように、SGML / XML / HTMLではないドキュメントを作成します。

  • ある時点で、ソースを連結したい場合があります。これは、cat source1.php source2.php終了?>タグを省略して不整合が生じた場合に行う場合ほど簡単ではありません。

  • これがない?>と、ドキュメントがPHPエスケープモードのままかPHP無視モードのままかを判断するのが難しくなります(PIタグ<?phpが開いているかどうか)。常にドキュメントをPHP無視モードのままにしておくと、作業が楽になります。これは、閉じられていない、正しくネストされていないタグなどがあるドキュメントと比較して、適切にフォーマットされたHTMLドキュメントで作業するのと同じです。

  • Dreamweaverなどの一部のエディターでは、PIを開いたままにしておくと問題が発生する可能性があります[1]


0

私が質問を正しく理解している場合、それは出力バッファリングに関係しており、これがタグの終了/終了に及ぼす影響があります。それが完全に有効な質問かどうかはわかりません。問題は、出力バッファがすべてのコンテンツをメモリに保持してからクライアントに送信することを意味しないことです。一部のコンテンツがそうであることを意味します。

プログラマーは意図的にバッファーまたは出力バッファーをフラッシュできるので、PHPの出力バッファーオプションは、終了タグがコーディングに与える影響を実際に変更しますか?私はそうではないと主張します。

そしておそらくそれが答えのほとんどが個人的なスタイルと構文に戻った理由です。


0

PHPコードの2つの可能な使用があります:

  1. クラス定義や関数定義などのPHPコード
  2. PHPをテンプレート言語として使用する(つまり、ビューで)

ケース1の場合。終了タグが完全に役に立たない。また、そのような場合は、1つ(1つ)のphpオープンタグとNO(ゼロ)だけの終了タグが欲しい。これにより、コードがクリーンになり、ロジックがプレゼンテーションから分離されるため、これは良い方法です。プレゼンテーションケース(2)では、すべてのタグ(PHPで処理されたタグも含む)を閉じるのが自然であることがわかりました。とプレゼンテーション

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.