# ユーザーレベルの出力バッファ

## 目次

- どの出力をバッファするのか？
- 出力バッファをネストさせる
- バッファサイズ
- バッファに対して可能な操作
- 出力ハンドラ
- 出力ハンドラを扱う
- 出力ハンドラに渡されるフラグ
- 出力ハンドラの戻り値

ユーザレベルの出力バッファは、 PHP コードから開始、操作、終了することができます。 バッファは、出力バッファと関連する出力ハンドラ関数を含みます。

## 出力バッファをオンにする

出力バッファリングは、php.ini 設定 output_buffering と output_handler を設定するか、ob_start() 関数を使うことでオンにできます。 これらは両方、出力バッファを生成できますが、 ob_start() の方がより柔軟です。 なぜなら、出力ハンドラをユーザー定義関数として受け入れますし、 (フラッシュ、クリーン、削除 のような) バッファに対する操作もできるからです。 ob_start() で開始したバッファは、 それをコールした行からアクティブになりますが、 output_buffering を使って開始したバッファは、スクリプトの最初の行から、出力をバッファします。

PHP は組み込みの `"URL-Rewriter"` 出力ハンドラをバンドルしています。 このハンドラは、自分の出力バッファを開始します。 同時に実行できるのはふたつです(1つはユーザレベルのURL書き換えと、 透過的なセッションIDサポートのためのもの) 。 これらのバッファは、output_add_rewrite_var() 関数をコールするか、php.ini 設定 session.use_trans_sid を有効にすることで開始できます。

バンドルされている `zlib` 拡張モジュールは、 独自の出力バッファを持っています。 この出力バッファは、php.ini 設定 zlib.output_compression を使うことで有効にできます。

> 注意: 一度に二つまでしか実行できないという意味で、 `"URL-Rewriter"` は特別です。 しかし、すべてのユーザレベルの出力バッファは、 カスタムの出力ハンドラ関数を指定して ob_start() をコールすることで開始した既存のバッファと同じものを使います。 そのため、すべての機能はユーザランドのコードでエミュレートすることができます。

## バッファの内容をフラッシュ/アクセス/削除する

フラッシュは、アクティブなバッファの内容を送信し、破棄します。 出力バッファは、出力のサイズがバッファのサイズを超えたときか、 スクリプトが終了するか、 ob_flush(), ob_end_flush(), ob_get_flush() のいずれかがコールされたときにフラッシュされます。

警告

ob_end_flush() や ob_get_flush() をコールすると、アクティブなバッファがオフになります。

警告

バッファをフラッシュすると、 出力バッファの戻り値がフラッシュされますが、 この値はバッファの内容と異なる場合があります。 例えば、ob_gzhandler() を使うと、出力が圧縮され、圧縮された出力がフラッシュされます。

アクティブなバッファの内容は ob_get_contents(), ob_get_clean(), ob_get_flush() をコールすると取得できます。

バッファの中身の長さだけが必要な場合、 ob_get_length() や ob_get_status() を使えばバッファの中身の長さをバイト単位で取得できます。

警告

ob_get_clean() や ob_get_flush() をコールすると、アクティブなバッファの中身を返した後、 そのバッファをオフにします。

アクティブなバッファの中身は、 ob_clean(), ob_end_clean(), ob_get_clean() を使って削除できます。

警告

ob_end_clean() や ob_get_clean() を使うと、アクティブなバッファがオフになります。

## 出力バッファをオフにする

ob_end_clean(), ob_end_flush(), ob_get_flush(), ob_get_clean() をコールすると、出力バッファをオフにできます。

警告

`PHP_OUTPUT_HANDLER_REMOVABLE` を指定せずに起動した出力バッファはオフにできず、 `E_NOTICE` が発生します。

スクリプトの終了時、または exit() がコールされるまでに閉じられていないすべての出力バッファは、 PHP のシャットダウン処理によってフラッシュされ、オフになります。 バッファは、起動した順序と逆の順序でフラッシュされ、オフになります。 最後にバッファリングが開始されたものが最初になり、 最初にバッファリングが開始されたものが最後にフラッシュされ、オフになります。

警告

バッファの内容をフラッシュしたくない場合は、 カスタムの出力ハンドラを使い、シャットダウン中のフラッシュを防ぐべきです。

## 出力ハンドラでスローされる例外

捕捉されない例外が出力ハンドラでスローされた場合、 プログラムは終了し、`"Uncaught Exception"` エラーメッセージがフラッシュされた後に、 シャットダウン処理によってハンドラが呼び出されます。

ob_flush(), ob_end_flush(), ob_get_flush() が呼び出したハンドラが、捕捉されない例外をスローした場合、 エラーメッセージがフラッシュされる前にバッファの内容がフラッシュされます。

シャットダウン処理中に出力ハンドラが捕捉されない例外をスローした場合、 ハンドラは終了し、バッファの内容もエラーメッセージもフラッシュされません。

> 注意: ハンドラが例外をスローした場合、 `PHP_OUTPUT_HANDLER_DISABLED` フラグが設定されます。

## 出力ハンドラで発生したエラー

出力ハンドラで致命的でないエラーが発生した場合、 プログラムの実行は継続されます。

ob_flush(), ob_end_flush(), ob_get_flush() が呼び出したハンドラで致命的でないエラーが発生した場合、 ハンドラの戻り値に応じて、バッファは一定のデータをフラッシュします。 ハンドラが `false` を返す場合、 バッファの中身とエラーメッセージがフラッシュされます。 それ以外の値をハンドラが返す場合、 ハンドラの戻り値はフラッシュされますが、エラーメッセージはフラッシュされません。

> 注意: ハンドラが `false` を返す場合、 `PHP_OUTPUT_HANDLER_DISABLED` フラグが設定されます。

出力ハンドラ中で致命的なエラーが発生した場合、 プログラムは終了し、 エラーメッセージがフラッシュされた後に、 シャットダウン処理によってハンドラが呼び出されます。

ob_flush(), ob_end_flush(), ob_get_flush() が呼び出したハンドラで、致命的なエラーが発生した場合、 エラーメッセージがフラッシュされる前にバッファの内容がフラッシュされます。

シャットダウン処理中に出力ハンドラで致命的なエラーが発生した場合、 プログラムは終了し、バッファの内容もエラーメッセージもフラッシュされません。

## 出力ハンドラで行われた出力

特定の状況下では、 ハンドラ内で生成された出力はバッファの内容と共にフラッシュされます。 この出力はバッファに追加されず、 ob_get_flush() が返す文字列の一部にもなりません。

フラッシュの操作中 (ob_flush(), ob_end_flush(), ob_get_flush() のコール中、またはシャットダウン処理中)に、 ハンドラが `false` を返した場合、 バッファの内容がフラッシュされ、その後に出力が行われます。 シャットダウン処理中にハンドラが呼び出されなかった場合、 ハンドラが例外をスローするか、exit() が呼び出されると、 同じ動作になります。

> 注意: ハンドラが `false` を返した場合、 `PHP_OUTPUT_HANDLER_DISABLED` が設定されます。

## 出力ハンドラのステータスフラグ

バッファが持つ `flags` ビットマスクの 出力ハンドラのステータスフラグ は、 出力ハンドラが起動されるたびに設定され、 ob_get_status() が返す `flags` の一部になります。 ハンドラが正常に実行され、`false` を返さなかった場合、 `PHP_OUTPUT_HANDLER_STARTED` と `PHP_OUTPUT_HANDLER_PROCESSED` が設定されます。 ハンドラが `false` を返すか、実行中に例外がスローされた場合は、 `PHP_OUTPUT_HANDLER_STARTED` と `PHP_OUTPUT_HANDLER_DISABLED` が設定されます。

> 注意: ハンドラの `PHP_OUTPUT_HANDLER_DISABLED` が設定されている場合、 ob_end_clean(), ob_end_flush(), ob_get_clean(), ob_get_flush() ob_clean(), ob_flush() 経由でハンドラは呼び出されません。 PHP のシャットダウン処理中でも同様です。 PHP 8.4.0 より前のバージョンでは、 ob_clean() や ob_flush() をコールしてもこのフラグはなんの意味もありませんでした。

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open