web-dev-qa-db-ja.com

phpでob_start()を使用するとどうなりますか?

ヘッダがバッファされてブラウザに送信されないように、ob_start()output bufferingに使用されますか。私はここで意味がありますか?そうでなければ、なぜob_start()を使うべきなのでしょうか。

264
Aditya Shukla

ob_start()は、「通常は出力されるはずのものはすべて覚えておきましょうが、まだ何もしないでください」と言っていると考えてください。

例えば:

ob_start();
echo("Hello there!"); //would normally get printed to the screen/output to browser
$output = ob_get_contents();
ob_end_clean();

ob_get_contents()は基本的にob_start()で起動されてからバッファに「保存された」ものをすべて提供し、次にob_end_clean()またはob_flush()は保存を中止して保存されたものを破棄する、または保存を中止してそれぞれ一斉に出力します。

427
Riley Dutton

私はこれを使っているので、たくさんのHTMLでPHPから抜け出すことはできますが、レンダリングはできません。それはIDE色分けを無効にする文字列としてそれを格納することから私を救います。

<?php
ob_start();
?>
<div>
    <span>text</span>
    <a href="#">link</a>
</div>
<?php
$content = ob_get_clean();
?>

の代わりに:

<?php
$content = '<div>
    <span>text</span>
    <a href="#">link</a>
</div>';
?>
139
JD Isaacks

ここで受け入れられている答えはob_start()が何をするのかを説明しています - それが使われる理由ではありません(これが質問でした)。

他の場所で述べたように、ob_start()は出力が書き込まれるバッファを作成します。

しかし、PHP内で複数のバッファをスタックすることは可能であるとは誰も述べていません。 ob_get_level ()を参照してください。

その理由は…….

  1. HTMLをより大きな部分に分けてブラウザに送信すると、ネットワークのオーバーヘッドが減少するため、パフォーマンスが向上します。

  2. 大きなチャンクでPHPからデータを渡すと、必要なコンテキストスイッチの数が減るため、パフォーマンスと容量が向上します。

  3. 大量のデータをmod_gzip/mod_deflateに渡すと、圧縮がより効率的になるという点でパフォーマンス上の利点があります。

  4. 出力をバッファするということは、コードの後半でHTTPヘッダを操作できるということです。

  5. [head] .... [/ head]を出力した後に明示的にバッファをフラッシュすると、ブラウザはHTMLストリームが完了する前にそのページの他のリソースの整列化を開始できます。

  6. 出力をバッファに取り込むことは、電子メールなどの他の機能にリダイレクトしたり、コンテンツのキャッシュ表現としてファイルにコピーしたりできることを意味します。

79
symcbean

あなたはそれを逆に持っています。 ob_startはヘッダーをバッファリングせず、コンテンツをバッファリングします。 ob_startを使用すると、コンテンツを表示する準備が整うまで、サーバーサイドのバッファにコンテンツを保存できます。

これは、ページがすでに何らかのコンテンツを「送った」後に(つまり、ページをレンダリングする途中でリダイレクトすることを決定する)ヘッダーを送信できるようにするためによく使用されます。

28
Craige

私は好きです:

ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
13
hawx

これはさらに明確にするためです JD Isaaksの回答 ...

あなたがよく遭遇する問題は、あなたが多くの異なるphpソースからhtmlを出力するためにphpを使用しているということです、そして、それらのソースはしばしば、何らかの理由で、異なる方法で出力しています。

場合によっては、ブラウザに直接出力したいリテラルHTMLコンテンツがあります。それ以外の場合、出力は動的に作成されています(サーバー側)。

動的コンテンツは常に(?)文字列になります。今度は、この文字列化された動的htmlをリテラルの直接表示html ...と1つの意味のあるhtmlノード構造に組み合わせる必要があります。

これは通常、(JD Isaakが説明したように)直接表示するすべてのコンテンツを文字列にラップすることを強制するため、動的HTMLと組み合わせて適切に配信/挿入できるようになります。それを包みたいです。

しかし、ob _ ##メソッドを使用することで、その文字列折り返しの混乱を避けることができます。リテラルの内容は、代わりにバッファに出力されます。それから簡単なステップでバッファの内容全体(あなたのリテラルなhtmlすべて)をあなたのdynamic-htmlストリングに連結する。

(私の例では、文字どおりのhtmlがバッファに出力されていて、それがhtml-stringに追加されています…JD Isaaksの例でもstring-wrapping-of-htmlを見てください)。

<?php // parent.php

//---------------------------------
$lvs_html  = "" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__without_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

$lvs_html .= "----<br/>" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__with_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

echo $lvs_html ;    
//    02 - component contents
//    html
//    01 - component header
//    03 - component footer
//    more html
//    ----
//    html
//    01 - component header
//    02 - component contents
//    03 - component footer
//    more html 

//---------------------------------
function gf_component_assembler__without_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;
    include( "component_contents.php" ) ;
    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
function gf_component_assembler__with_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;

        ob_start();
        include( "component_contents.php" ) ;
    $lvs_html .= ob_get_clean();

    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
?>

<!-- component_contents.php -->
  <div>
    02 - component contents
  </div>
7
dsdsdsdsd

この関数はヘッダ専用ではありません。あなたはこれでたくさんの面白いことをすることができます。例:あなたはあなたのページをセクションに分割してそれを次のように使うことができます:

$someTemplate->selectSection('header');
echo 'This is the header.';

$someTemplate->selectSection('content');
echo 'This is some content.';

ここで生成された出力をキャプチャして、レイアウト内のまったく異なる2箇所に追加することができます。

3
jwueller

現在の回答では、次のことは言及されていません。バッファサイズの設定HTTPヘッダーとネスティング。

Ob_startのバッファサイズ設定:

ob_start(null, 4096); // Once the buffer size exceeds 4096 bytes, PHP automatically executes flush, ie. the buffer is emptied and sent out.

上記のコードでは、PHPが4KBなど、より大きなデータを送信するため、サーバーのパフォーマンスが向上します(ob_start呼び出しを行わずにphpを実行すると、各エコーがブラウザに送信されます)。

チャンクサイズなしでバッファリングを開始した場合(つまり、単純なob_start())、ページはスクリプトの最後に1回送信されます。

出力バッファリングはHTTPヘッダに影響を与えません、それらは異なった方法で処理されます。ただし、バッファリングにより、出力が送信された後でもヘッダーを送信できます。これはまだバッファー内にあるためです。

ob_start();  // turns on output buffering
$foo->bar();  // all output goes only to buffer
ob_clean();  // delete the contents of the buffer, but remains buffering active
$foo->render(); // output goes to buffer
ob_flush(); // send buffer output
$none = ob_get_contents();  // buffer content is now an empty string
ob_end_clean();  // turn off output buffering

ここでうまく説明されています: https://phpfashion.com/everything-about-output-buffering-in-php

0
sudip

いいえ、あなたは間違っています、しかし方向は合います;)

Output-Bufferingは、スクリプトの出力をバッファリングします。 echoまたはprintの後にeverthingすると簡単に言えば。ヘッダに関することは、まだ送信されていない場合にのみ送信されるということです。しかしHTTPは、ヘッダが送信の最初のものであると言っています。そのため、(リクエストで)初めて何かを出力した場合、ヘッダが送信され、他のヘッダを設定することはできません。

0
KingCrunch