【PHP】処理の途中経過を逐次出力。flushが上手くいかないときは…。

PHPで、例えば以下のような 1 秒ごとに数字を出力するスクリプトを書いてブラウザ上で実行してみても、結果は実行終了後にまとめて表示されます。

<?php

for( $i = 0 ; $i < 20 ; $i++){
    echo $i;
    sleep(1);
}

?>

処理の途中で結果を出力させるには flush() を使えば良いです。ウェブサーバの出力バッファリングやウェブブラウザのバッファリングやらを考慮すると、うちの環境だと以下のような感じで上手くいく。

<?php

for( $i = 0 ; $i < 20 ; $i++){
    echo str_repeat( ' ' , 1024*4 );
    echo $i;
    ob_flush();
    flush();
    sleep(1);
}

?>

バッファを 1024*4 個のスペースで一杯にして $i を出力。それを ob_flush()、flush()で表示する…という具合。

で、ウェブサーバのほうで「コンテンツを gzip 圧縮して送信する」という設定がされていると、上記のコードでも狙った動作をしてくれません。スクリプトの実行終了後に、まとめて表示が行われてしまいます。flushが上手く動作しないときには、これをチェックしてみてください。

回避するには、PHPファイルの gzip 圧縮を無効にすれば良いです。サーバで Apache が稼働している場合は、当該のPHPスクリプトがあるディレクトリ(もしくはそれより上位のディレクトリ)に、

# ファイル名の末尾が .php であるファイルに対して gzip 圧縮を抑止
<FilesMatch \.php>
    SetEnv no-gzip 1
</FilesMatch>

…という .htaccess ファイルを設置すればOK。

ということで。

カテゴリ: