PHP
出力バッファリング
サーチ…
パラメーター
関数 | 詳細 |
---|---|
ob_start() | 出力バッファを開始し、その後に置かれた出力はキャプチャされ、表示されません |
ob_get_contents() | ob_start() によってob_start() されたすべてのコンテンツを返します。 |
ob_end_clean() | 出力バッファを空にし、現在の入れ子レベルで出力バッファをオフにします。 |
ob_get_clean() | ob_get_contents() とob_end_clean() 両方をトリガしob_end_clean() |
ob_get_level() | 出力バッファの現在のネストレベルを返します。 |
ob_flush() | コンテンツバッファをフラッシュし、バッファを終了せずにブラウザに送信します。 |
ob_implicit_flush() | 出力コールごとに暗黙的なフラッシュを有効にします。 |
ob_end_flush() | コンテンツバッファをフラッシュしてブラウザに送信し、バッファを終了する |
バッファ間のコンテンツの取得とクリア
出力バッファリングを使用すると、任意のテキストコンテンツ(テキスト、 HTML
)を変数に格納し、スクリプトの最後にブラウザに送信することができます。デフォルトでは、 php
あなたのコンテンツをそれを解釈するときに送信します。
<?php
// Turn on output buffering
ob_start();
// Print some output to the buffer (via php)
print 'Hello ';
// You can also `step out` of PHP
?>
<em>World</em>
<?php
// Return the buffer AND clear it
$content = ob_get_clean();
// Return our buffer and then clear it
# $content = ob_get_contents();
# $did_clear_buffer = ob_end_clean();
print($content);
#> "Hello <em>World</em>"
ob_start()
とob_get_clean()
間で出力されたコンテンツはすべてキャプチャされ、変数$content
ob_get_clean()
されます。
ob_get_clean()
呼び出すと、 ob_get_contents()
とob_end_clean()
両方がトリガされます。
ネストされた出力バッファ
ob_get_level()
関数を使用して、出力バッファをネストし、それらが異なるコンテンツを提供するためのレベルをフェッチすることができます。
<?php
$i = 1;
$output = null;
while( $i <= 5 ) {
// Each loop, creates a new output buffering `level`
ob_start();
print "Current nest level: ". ob_get_level() . "\n";
$i++;
}
// We're at level 5 now
print 'Ended up at level: ' . ob_get_level() . PHP_EOL;
// Get clean will `pop` the contents of the top most level (5)
$output .= ob_get_clean();
print $output;
print 'Popped level 5, so we now start from 4' . PHP_EOL;
// We're now at level 4 (we pop'ed off 5 above)
// For each level we went up, come back down and get the buffer
while( $i > 2 ) {
print "Current nest level: " . ob_get_level() . "\n";
echo ob_get_clean();
$i--;
}
出力:
Current nest level: 1
Current nest level: 2
Current nest level: 3
Current nest level: 4
Current nest level: 5
Ended up at level: 5
Popped level 5, so we now start from 4
Current nest level: 4
Current nest level: 3
Current nest level: 2
Current nest level: 1
後で再利用するために出力バッファをキャプチャする
この例では、いくつかのデータを含む配列があります。
$items_li_html
出力バッファをキャプチャし、ページで2回使用します。
<?php
// Start capturing the output
ob_start();
$items = ['Home', 'Blog', 'FAQ', 'Contact'];
foreach($items as $item):
// Note we're about to step "out of PHP land"
?>
<li><?php echo $item ?></li>
<?php
// Back in PHP land
endforeach;
// $items_lists contains all the HTML captured by the output buffer
$items_li_html = ob_get_clean();
?>
<!-- Menu 1: We can now re-use that (multiple times if required) in our HTML. -->
<ul class="header-nav">
<?php echo $items_li_html ?>
</ul>
<!-- Menu 2 -->
<ul class="footer-nav">
<?php echo $items_li_html ?>
</ul>
上記のコードをoutput_buffer.php
ファイルに保存し、 php output_buffer.php
実行します。
上記で作成した2つのリスト項目は、出力バッファを使用してPHPで生成したものと同じリスト項目で表示されます。
<!-- Menu 1: We can now re-use that (multiple times if required) in our HTML. -->
<ul class="header-nav">
<li>Home</li>
<li>Blog</li>
<li>FAQ</li>
<li>Contact</li>
</ul>
<!-- Menu 2 -->
<ul class="footer-nav">
<li>Home</li>
<li>Blog</li>
<li>FAQ</li>
<li>Contact</li>
</ul>
コンテンツの前に出力バッファを実行する
ob_start();
$user_count = 0;
foreach( $users as $user ) {
if( $user['access'] != 7 ) { continue; }
?>
<li class="users user-<?php echo $user['id']; ?>">
<a href="<?php echo $user['link']; ?>">
<?php echo $user['name'] ?>
</a>
</li>
<?php
$user_count++;
}
$users_html = ob_get_clean();
if( !$user_count ) {
header('Location: /404.php');
exit();
}
?>
<html>
<head>
<title>Level 7 user results (<?php echo $user_count; ?>)</title>
</head>
<body>
<h2>We have a total of <?php echo $user_count; ?> users with access level 7</h2>
<ul class="user-list">
<?php echo $users_html; ?>
</ul>
</body>
</html>
この例では、 $users
を多次元配列と仮定し、それをループしてアクセスレベルが7のすべてのユーザーを検索します。
結果がない場合は、エラーページにリダイレクトされます。
ループの結果に基づいてheader()
リダイレクトをトリガーするので、ここで出力バッファを使用しています
出力バッファを使用してコンテンツをファイルに保存し、レポート、請求書などに便利
<?php
ob_start();
?>
<html>
<head>
<title>Example invoice</title>
</head>
<body>
<h1>Invoice #0000</h1>
<h2>Cost: £15,000</h2>
...
</body>
</html>
<?php
$html = ob_get_clean();
$handle = fopen('invoices/example-invoice.html', 'w');
fwrite($handle, $html);
fclose($handle);
この例では、完全なドキュメントを取得してファイルにecho $html;
が、ドキュメントをブラウザに出力するのではなく、 echo $html;
を使用してドキュメントを出力しますecho $html;
コールバックによるバッファの処理
コール可能オブジェクトをob_start()
渡すことによって、出力に任意の種類の追加処理を適用できます。
<?php
function clearAllWhiteSpace($buffer) {
return str_replace(array("\n", "\t", ' '), '', $buffer);
}
ob_start('clearAllWhiteSpace');
?>
<h1>Lorem Ipsum</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. <a href="#">Donec non enim</a> in turpis pulvinar facilisis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<?php
/* Output will be flushed and processed when script ends or call
ob_end_flush();
*/
出力:
<h1>LoremIpsum</h1><p><strong>Pellentesquehabitantmorbitristique</strong>senectusetnetusetmalesuadafamesacturpisegestas.<ahref="#">Donecnonenim</a>inturpispulvinarfacilisis.</p><h2>HeaderLevel2</h2><ol><li>Loremipsumdolorsitamet,consectetueradipiscingelit.</li><li>Aliquamtinciduntmauriseurisus.</li></ol>
クライアントへのストリーム出力
/**
* Enables output buffer streaming. Calling this function
* immediately flushes the buffer to the client, and any
* subsequent output will be sent directly to the client.
*/
function _stream() {
ob_implicit_flush(true);
ob_end_flush();
}
ob_startを使用する典型的な使用法とその理由
ob_start
は、ページのリダイレクトを行うと便利です。たとえば、次のコードは機能しません。
Hello!
<?php
header("Location: somepage.php");
?>
与えられるエラーheaders already sent by <xxx> on line <xxx>
ようなものです。
この問題を解決するには、ページの先頭に次のような記述をします。
<?php
ob_start();
?>
あなたのページの最後にこういうものがあります:
<?php
ob_end_flush();
?>
生成されたすべてのコンテンツが出力バッファに保存され、一度に表示されます。したがって、ページにリダイレクト呼び出しがあると、データが送信される前にトリガーされ、 headers already sent
たheaders already sent
エラーが発生する可能性がheaders already sent
ます。