PHPのob_start関数の役割や使い方について

採用はこちら

ob_start()は、PHPの出力バッファリングを開始する関数です。

PHPでは、echoprint、PHPファイル内に直接記述したHTMLなどによって出力が生成されます。
ob_start()を実行すると、その後に生成された対象の出力をユーザーレベルの出力バッファへ一時的に蓄積できるようになります。

蓄積した出力は、あとから文字列として取得したり、加工したり、破棄したり、まとめて出力したりできます。

基本的な使い方は次のとおりです。

<?php

ob_start();

echo 'Hello World';

$content = ob_get_clean();

echo $content;

このコードでは、echo 'Hello World';の内容がいったん出力バッファへ保存されます。
その後、ob_get_clean()によってバッファの内容を文字列として取得し、バッファリングを終了しています。

ob_start()は、HTMLテンプレートの出力を変数として取得したい場合や、出力内容を加工したい場合などに便利な関数です。

目次

ob_start関数の基本的な使い方

ob_startで出力バッファリングを開始する

出力バッファリングを開始するには、次のように記述します。

ob_start();

ob_start()の実行後に生成された出力は、現在の出力バッファへ蓄積されます。

例えば、次のコードがあります。

<?php

ob_start();

echo 'PHP';
echo 'を学習します';

この場合、echoによって生成された文字列は出力バッファに保存されます。

ただし、PHPの設定によっては、ob_start()を明示的に呼び出していなくても出力バッファリングが有効になっている場合があります。
そのため、ob_start()は「PHPで唯一の出力バッファリング方法」ではなく、プログラムからユーザーレベルの出力バッファを開始するための関数と理解すると正確です。

バッファの内容を取得する

現在の出力バッファの内容を取得するには、ob_get_contents()を使用します。

<?php

ob_start();

echo 'Hello';
echo ' World';

$content = ob_get_contents();

echo $content;

$contentには、次の文字列が格納されます。

Hello World

ただし、ob_get_contents()はバッファの内容を取得するだけで、バッファリング自体は終了しません。

バッファリングを終了したい場合は、ob_end_clean()ob_end_flush()などを使用します。

ob_get_cleanと組み合わせる方法

出力内容を取得してバッファを終了する

ob_start()とよく組み合わせて使用されるのが、ob_get_clean()です。

<?php

ob_start();

echo '<h1>PHP入門</h1>';
echo '<p>ob_startのサンプルです。</p>';

$html = ob_get_clean();

echo $html;

ob_get_clean()は、現在の出力バッファの内容を取得し、そのバッファを終了します。

そのため、次の処理をまとめて記述できます。

$content = ob_get_contents();
ob_end_clean();

これを簡潔にすると、次のようになります。

$content = ob_get_clean();

HTMLやテンプレートの出力を文字列として取得したい場合には、非常によく使われる書き方です。

ob_startでHTMLを変数に保存する方法

HTMLをそのまま記述できる

ob_start()を使うと、複雑なHTMLを文字列連結せずに変数へ保存できます。

例えば、通常の文字列連結では次のようになります。

$html = '<div class="article">';
$html .= '<h2>タイトル</h2>';
$html .= '<p>本文です。</p>';
$html .= '</div>';

ob_start()を使えば、次のようにHTMLを通常どおり記述できます。

<?php

ob_start();

?>

<div class="article">
    <h2>タイトル</h2>
    <p>本文です。</p>
</div>

<?php

$html = ob_get_clean();

これでHTML全体が $html に文字列として格納されます。

複雑なHTMLを扱う場合は、文字列を何度も連結するより読みやすくなることがあります。

includeしたPHPファイルの出力を取得する方法

テンプレートの実行結果を文字列として取得する

ob_start()は、includerequireで読み込んだPHPファイルの出力を取得するときにも利用できます。

例えば、template.phpが次の内容だったとします。

<h1>Hello</h1>
<p>PHP Template</p>

次のように記述します。

<?php

ob_start();

include 'template.php';

$html = ob_get_clean();

$htmlには、template.phpが生成したHTMLが文字列として格納されます。

この方法は、簡易的なテンプレート処理やビューのレンダリング処理を実装する場合などに利用できます。

ob_startのコールバック関数とは

出力内容を加工してから処理できる

ob_start()には、出力ハンドラとしてコールバック関数を指定できます。

ob_start($callback);

例えば、出力中の文字列を置換する場合は次のように記述できます。

<?php

ob_start(function ($buffer) {
    return str_replace('PHP', 'PHP言語', $buffer);
});

echo 'PHPを学習します';

ob_end_flush();

最終的な出力は次のようになります。

PHP言語を学習します

処理のイメージは次のとおりです。

PHPが出力を生成
↓
出力バッファへ保存
↓
コールバックで加工
↓
最終的な出力

コールバックは1回だけ実行されるとは限らない

出力ハンドラとして指定したコールバックは、必ずしもスクリプト終了時に1回だけ呼び出されるわけではありません。

バッファのフラッシュや終了などのタイミングでも呼び出される可能性があります。

高度な処理では、次のように第2引数を受け取ることもできます。

function handler(string $buffer, int $phase): string
{
    return $buffer;
}

$phaseには、出力ハンドラがどのタイミングで呼び出されたかを示す情報が渡されます。

単純な文字列置換だけであれば、1つ目の $bufferだけを使用する書き方でも問題ありません。

コールバック内で一部のob関数を呼ばない

ob_start()のコールバック内では、出力バッファを操作する一部の関数を呼び出せません。

例えば、次のような関数です。

ob_clean();
ob_end_clean();
ob_end_flush();
ob_flush();
ob_get_clean();
ob_get_flush();
ob_start();

出力ハンドラの内部からこれらを実行すると、Fatal Errorになる可能性があります。

そのため、出力バッファの開始や終了は、基本的にコールバックの外側で管理します。

ob_startの引数

ob_start()は、主に次のような構文で使用します。

ob_start(
    ?callable $callback = null,
    int $chunk_size = 0,
    int $flags = PHP_OUTPUT_HANDLER_STDFLAGS
): bool

主な引数は次の3つです。

callback
chunk_size
flags

callback

callbackには、出力内容を加工するコールバック関数を指定します。

ob_start(function ($buffer) {
    return strtoupper($buffer);
});

例えば、

echo 'hello';

と出力すると、最終的に次のように変換できます。

HELLO

コールバックが不要であれば、省略できます。

ob_start();

一般的な用途では、この書き方で十分です。

chunk_size

chunk_sizeは、バッファをフラッシュするためのしきい値を指定する引数です。

例えば、次のように指定できます。

ob_start(null, 4096);

出力によってバッファサイズが指定値以上になると、バッファの内容が処理されます。

ただし、4096を指定したからといって、必ず正確に4,096バイト単位で出力されるという意味ではありません。

あくまでも、バッファを処理するためのしきい値として理解するのが適切です。

デフォルト値の 0では、通常はバッファが明示的にフラッシュまたは終了されるまで内容が保持されます。

flags

flagsでは、出力バッファに対して許可する操作を指定できます。

代表的な定数には次のものがあります。

PHP_OUTPUT_HANDLER_CLEANABLE
PHP_OUTPUT_HANDLER_FLUSHABLE
PHP_OUTPUT_HANDLER_REMOVABLE
PHP_OUTPUT_HANDLER_STDFLAGS

主な意味は次のとおりです。

PHP_OUTPUT_HANDLER_CLEANABLE
バッファ内容の消去を許可する

PHP_OUTPUT_HANDLER_FLUSHABLE
バッファのフラッシュを許可する

PHP_OUTPUT_HANDLER_REMOVABLE
バッファの終了・削除を許可する

PHP_OUTPUT_HANDLER_STDFLAGSは、通常利用される標準的なフラグの組み合わせです。

一般的なPHPコードでは、flagsを明示的に変更する必要はほとんどありません。

なお、PHPのバージョンによって高度な出力ハンドラ制御の仕様が変更されている場合があるため、特殊な制御を行う場合は使用しているPHPバージョンの仕様を確認することが重要です。

ob_startと一緒に使われる主な関数

ob_get_contents

現在の出力バッファの内容を取得します。

$content = ob_get_contents();

バッファ自体は終了しません。

ob_get_clean

現在の出力バッファの内容を取得し、そのバッファを終了します。

$content = ob_get_clean();

HTMLやテンプレートの出力を文字列として取得するときに便利です。

ob_clean

現在の出力バッファの内容を消去します。

ob_clean();

バッファ自体は終了しないため、その後も出力を蓄積できます。

ob_end_clean

現在の出力バッファの内容を破棄し、バッファを終了します。

ob_end_clean();

途中で生成された出力をユーザーへ表示したくない場合などに利用できます。

ob_flush

現在の出力バッファの内容をフラッシュします。

ob_flush();

バッファ自体は終了しません。

そのため、フラッシュしたあとも同じバッファへ新しい出力を蓄積できます。

ob_end_flush

現在のバッファ内容をフラッシュし、そのバッファを終了します。

ob_end_flush();

つまり、概念的には次のような処理です。

バッファの内容を処理する
+
現在のバッファを終了する

ob_startとob_end_flushの違い

ob_startはバッファを開始する

ob_start()は、出力バッファリングを開始する関数です。

ob_start();

その後の対象となる出力がバッファに蓄積されます。

ob_end_flushは出力してバッファを終了する

ob_end_flush()は、現在の出力バッファの内容をフラッシュし、バッファを終了します。

<?php

ob_start();

echo 'Hello World';

ob_end_flush();

処理の流れは次のようになります。

ob_start()
↓
出力バッファリング開始
↓
echoで出力生成
↓
ob_end_flush()
↓
バッファをフラッシュ
↓
バッファ終了

ob_startとob_get_cleanの違い

開始と取得・終了という役割の違いがある

ob_start()ob_get_clean()はセットで使われることが多い関数ですが、役割は異なります。

ob_start();

echo 'Hello';

$content = ob_get_clean();

処理の流れは次のとおりです。

ob_start()
↓
出力バッファを開始
↓
echoの内容を保存
↓
ob_get_clean()
↓
内容を文字列として取得
↓
バッファ終了

テンプレートのHTMLを変数へ保存するときには、特に使いやすい組み合わせです。

ob_startを使うメリット

HTMLを文字列として扱いやすい

ob_start()を使うと、通常のHTMLをそのまま記述しながら、生成結果を文字列として取得できます。

ob_start();
?>

<div>
    <h2>タイトル</h2>
    <p>本文です。</p>
</div>

<?php
$html = ob_get_clean();

複雑なHTMLを大量に文字列連結する必要がなくなるため、コードを読みやすくできる場合があります。

PHPテンプレートの出力を取得できる

includeしたPHPファイルの出力も取得できます。

ob_start();

include 'template.php';

$content = ob_get_clean();

テンプレートを文字列としてレンダリングしたい場合に便利です。

出力内容を加工できる

コールバック関数を指定すれば、最終的な出力を加工できます。

ob_start(function ($buffer) {
    return str_replace('foo', 'bar', $buffer);
});

文字列置換など、出力全体へ共通処理を行いたい場合に利用できます。

不要な出力を破棄できる

意図せず出力を生成する処理を一時的にバッファへ閉じ込めて、破棄することもできます。

ob_start();

some_function();

ob_end_clean();

この場合、some_function()が通常のPHP出力を生成したとしても、現在のバッファ内容を破棄できます。

ob_startで捕捉できる出力

echoやHTMLなどが対象になる

ob_start()による出力バッファリングでは、PHPの出力経路を通るデータが対象になります。

代表的なものは次のとおりです。

echoによる出力
printによる出力
PHPファイル内に直接記述したHTML
includeやrequireしたPHPファイルの出力

例えば、

ob_start();

echo 'Hello';

$content = ob_get_clean();

であれば、echoによる出力を取得できます。

すべての処理結果を取得できるわけではない

ob_start()は、PHPで発生するすべての処理を記録する関数ではありません。

例えば、次のような処理は通常の出力バッファの対象とは異なります。

file_put_contents();
fwrite();
error_log();

データベースへのINSERTやUPDATEなども、出力バッファへ保存されるわけではありません。

そのため、ob_start()はログ収集機能や処理履歴保存機能ではなく、PHPの出力を制御するための機能として理解することが重要です。

ob_startとheader関数の関係

headers already sentを回避できる場合がある

PHPでは、HTTPレスポンスの出力が開始されたあとに header()を実行すると、次のようなエラーが発生することがあります。

Cannot modify header information - headers already sent

ob_start()を使用すると、出力がまだバッファ内に留まっている間は、header()を利用できる場合があります。

<?php

ob_start();

echo 'Hello';

header('Location: /example.php');

ob_end_clean();

exit;

ただし、ob_start()はHTTPヘッダーそのものを保存するための関数ではありません。

echoなどによる出力がPHPの出力バッファに留まることで、結果としてHTTPヘッダーを変更できる状態が維持される場合があるという仕組みです。

根本的には出力順序を見直す

ob_start()を「headers already sentエラーを解消するための関数」と考えるのは適切ではありません。

通常は、

header();
setcookie();
session_start();

などHTTPヘッダーへ影響する処理を、HTMLや echoによる出力より前に実行する設計が望ましいです。

ob_start()による回避は、必要な場合に利用する手段の一つと考えましょう。

ob_startを使う際の注意点

大量のデータを蓄積するとメモリを使用する

出力バッファへ保存されたデータはメモリを使用します。

例えば、非常に大きなHTMLやデータをすべて一度に保存すると、メモリ消費量が増える可能性があります。

ob_start();

// 大量の出力

$data = ob_get_clean();

大容量ファイルの配信やストリーミングなどでは、すべての出力をバッファへ蓄積する方法が適していない場合があります。

flushしてもすぐブラウザへ表示されるとは限らない

次のように記述することがあります。

ob_flush();
flush();

しかし、これを実行したからといって、ユーザーのブラウザに即座に表示されるとは限りません。

PHPの外側にも、

PHP
↓
PHP-FPMやFastCGI
↓
Webサーバー
↓
リバースプロキシ
↓
HTTP圧縮
↓
ブラウザ

など、複数の処理レイヤーが存在する可能性があります。

それぞれの場所で独自のバッファリングが行われることがあるためです。

リアルタイム表示やストリーミングを実装する場合は、PHPだけでなくWebサーバーやプロキシなどの設定も確認する必要があります。

バッファを適切に終了する

ob_start()で開始した出力バッファは、用途に応じて明示的に終了するとコードの意図が分かりやすくなります。

例えば、内容を取得する場合は、

$content = ob_get_clean();

内容を破棄する場合は、

ob_end_clean();

出力して終了する場合は、

ob_end_flush();

を使用します。

PHPスクリプト終了時に残っているバッファが処理される場合もありますが、意図した階層のバッファを確実に管理するためにも、明示的に処理するほうが分かりやすいでしょう。

ob_startはネストできる

複数の出力バッファを重ねられる

ob_start()は、すでに出力バッファが存在する状態でもさらに呼び出せます。

<?php

ob_start();

echo 'Outer';

ob_start();

echo 'Inner';

$inner = ob_get_clean();

echo $inner;

$outer = ob_get_clean();

このように、出力バッファを階層化できます。

現在のバッファ階層は、ob_get_level()で確認できます。

$level = ob_get_level();

フレームワークやCMSなどでは内部的に出力バッファを使用している場合があるため、自分が開始していないバッファまで不用意に終了しないよう注意が必要です。

ob_startをテンプレート処理に活用する方法

テンプレートのレンダリング関数を作る

ob_start()を利用すると、PHPテンプレートを文字列として返す関数を作れます。

<?php

function render(string $template, array $data = []): string
{
    extract($data, EXTR_SKIP);

    ob_start();

    include $template;

    return ob_get_clean();
}

例えば、次のように呼び出します。

$html = render('profile.php', [
    'name' => 'Taro',
]);

echo $html;

profile.php内で生成されたHTMLが $htmlへ格納されます。

ただし、extract()は配列のキーを変数として展開する関数なので、変数名の衝突や意図しない上書きに注意が必要です。

実際のアプリケーションでは、フレームワークのテンプレート機能を使用したり、extract()を使用しない設計を採用したりする方法もあります。

ob_startの代表的な使用パターン

出力を文字列として取得する場合

ob_start();

echo 'Hello';

$content = ob_get_clean();

テンプレートなどの出力結果を変数として使いたい場合に適しています。

出力してバッファを終了する場合

ob_start();

echo 'Hello';

ob_end_flush();

蓄積した内容を処理して、現在のバッファを終了します。

出力を破棄する場合

ob_start();

echo 'Hello';

ob_end_clean();

バッファ内の内容を出力せずに破棄します。

内容だけ取得してバッファを継続する場合

ob_start();

echo 'Hello';

$content = ob_get_contents();

ob_get_contents()では、バッファの内容を取得してもバッファ自体は終了しません。

その後も出力を追加できます。

PHPのob_start関数を正しく理解しよう

ob_start()は、PHPのユーザーレベルの出力バッファリングを開始し、生成された出力をプログラム側で制御できるようにする関数です。

出力をいったんバッファへ保存することで、

HTMLを文字列として取得する
テンプレートの出力を取得する
出力内容を加工する
不要な出力を破棄する
出力のタイミングを制御する

といった処理が可能になります。

特に覚えておくと便利なのが、次の組み合わせです。

ob_start();

// HTMLやechoなどの出力

$content = ob_get_clean();

このパターンを理解しておけば、PHPテンプレートの実行結果を文字列として扱う処理などを実装しやすくなります。

ただし、ob_start()はHTTPヘッダーそのものをバッファリングする関数ではなく、すべてのPHP処理を記録する機能でもありません。

また、大量のデータをバッファリングする場合のメモリ消費や、Webサーバー・リバースプロキシなどPHP以外のバッファリングにも注意が必要です。

ob_start()を単に「出力を遅らせる関数」と考えるのではなく、PHPが生成した出力を取得・加工・破棄・フラッシュするための出力制御機能として理解すると、適切に活用しやすくなります。

以上、PHPのob_start関数の役割や使い方についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次