Do You PHP はてな このページをアンテナに追加 RSSフィード Twitter

2007-04-26

[]出力バッファとflush()・ob_flush()

f:id:shimooka:20061025123905p:image

しばらく使わないとすっかり忘れてしまうので、まとめてメモ。

ありがちなネタとして、

  • プログレスバー(進捗状況をリアルタイムに表示)
  • 「お待ちください」と表示させて裏で処理を実行し、処理が終わったら結果を表示する

などがありますが、これらを行うには出力データのバッファリング/フラッシュを行うことになります。

で、PHP的にはob_*関数やflush関数を使うことになりますが、 [PHP-users 18135]プログレスバーは実現可能か? スレッドから

  • flush()が動作する条件は、出力バッファが無いこと
  • ob_flush()が動作する条件は、出力バッファのネストレベルが1であること
  • 出力バッファのネストレベルはob_get_level()で取得できる
    • output_handler、output_buffer(> 0)を指定すると、ネストレベルが変わります

という注意点が挙げられます。

たとえば、 [PHP-users 18141]Re: プログレスバーは実現可能か? にあるコードを元にした以下のようなコード

<?php
echo 'ob_get_level()=' . ob_get_level() . '<br>';
ob_end_flush();
echo 'ob_get_level()=' . ob_get_level() . '<br>';
ob_start();
echo 'ob_get_level()=' . ob_get_level() . '<br>';
for ( $i = 1; $i <= 100000; $i++ ) {
    if ($i % 100 == 0) {    //DATA_UNIT=100
        echo "";
        if (($i % 1000 == 0)) {
            echo "|";
        }
        if ($i % 5000 == 0) {
            echo "<br>";
            usleep(200000);
        }
        ob_flush();
        flush();
    }
}
echo 'finish';

の場合、output_handler=none、output_buffer > 0の場合や、mbstring.http_outputが適切に設定されている場合の出力結果は

ob_get_level()=1
ob_get_level()=0
ob_get_level()=1
...

となり、ネストレベルが1なので、期待通りバッファリング/フラッシュされます。

ただし、mbstring.internal_encoding(mbstring.script_encodingを指定している場合はこれ)とmbstring.http_outputが異なる場合、ネストレベルが一度0になってしまうと文字化けを起こす場合があります。この場合は、

<?php
//ob_end_flush();
//ob_start();

とするか

<?php
ob_end_flush();
ob_start('mb_output_handler');

とすればOKです。

まあ、いずれにしても「出力バッファのネストレベルを1にする」と覚えておけばヨサゲです。

yamazonyamazon 2010/02/20 21:54 はじめまして。phpでプログラムの進み具合を表示させる機能について調べていました。
とても参考になりました。ありがとうございました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

Connection: close