クライアントへのログのみを生成する php スクリプトがあります。
何かをエコーするとき、オンザフライでクライアントに転送したい。
(スクリプトの処理中はページが空白なので)
と をいじっていましたが、うまくいきませんでしたob_start()
。ob_flush()
最善の解決策は何ですか?
echo
PS:呼び出しの最後にフラッシュを置くのは少し汚いです...
編集:どちらの回答も機能しませんでした.PHPまたはApache Fault?
私は同じ問題を抱えており、マニュアルに掲載されている例の1つが機能しました。文字セットは、ここで既に説明したポスターの 1 つとして指定する必要があります。http://www.php.net/manual/en/function.ob-flush.php#109314
header( 'Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
for( $i = 0 ; $i < 10 ; $i++ )
{
echo $i . '<br />';
flush();
ob_flush();
sleep(1);
}
echo 'End ...<br />';
編集:
マニュアルページのコメントを読んでいて、それが機能しないというバグに遭遇しました。次の回避策があります。ob_implicit_flush
ob_end_flush();
# CODE THAT NEEDS IMMEDIATE FLUSHING
ob_start();
これが機能しない場合、サーバーがパケットを送信する価値があると見なすものを送信するのに十分な文字を構築するまで、クライアントがサーバーからパケットを受信しない可能性さえあります。
古い答え:
ob_implicit_flush
出力バッファリングにしばらくの間バッファリングをオフにするように指示する which を使用できます。
ob_implicit_flush(true);
# CODE THAT NEEDS IMMEDIATE FLUSHING
ob_implicit_flush(false);
これが私が見つけたものです。
フラッシュは、論理的にはコンテンツをgzipで圧縮しているため、Apacheのmod_gzipまたはNginxのgzipでは機能しません。そのためにはコンテンツをバッファリングしてgzipで圧縮する必要があります。あらゆる種類のWebサーバーのgzipがこれに影響します。つまり、サーバー側でgzipを無効にし、fastcgiバッファーサイズを減らす必要があります。それで:
php.iniの場合:
output_buffering = Off
zlib.output_compression = Off
nginx.confの場合:
gzip off;
proxy_buffering off;
また、特にphp.iniにアクセスできない場合は、次の行を手元に用意してください。
@ini_set('zlib.output_compression',0);
@ini_set('implicit_flush',1);
@ob_end_clean();
set_time_limit(0);
最後に、お持ちの場合は、次のコードにコメントしてください。
ob_start('ob_gzhandler');
ob_flush();
PHPテストコード:
ob_implicit_flush(1);
for ($i=0; $i<10; $i++) {
echo $i;
// this is to make the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
sleep(1);
}
一見うまくいかないフラッシュは、自動文字セット検出の副作用です。
ブラウザは、表示する文字セットがわかるまで何も表示しません。文字セットを指定しない場合は、推測する必要があります。問題は、十分なデータがないと適切な推測ができないことです。これが、ブラウザーが何かを表示する前に、この 1024 バイト (または同様の) バッファーを埋める必要があるように見える理由です。
したがって、解決策は、ブラウザーが文字セットを推測する必要がないようにすることです。
テキストを送信する場合は、'; を追加します。charset=utf-8' をコンテンツ タイプに追加し、HTML の場合は、文字セットを適切なメタ タグに追加します。
あなたが望むのはフラッシュメソッドです。例:
echo "log to client";
flush();
次のように、エコーする関数を作成してみませんか。
function fecho($string) {
echo $string;
ob_flush();
}
私も同様のことをしました。使用する
// ini_set("output_buffering", 0); // off
ini_set("zlib.output_compression", 0); // off
ini_set("implicit_flush", 1); // on
私の場合、出力フラッシュを頻繁に行いました。
しかし、特定の時点(実行するループ内)で出力をフラッシュする必要があったため、両方を使用して
ob_flush();
flush();
一緒に私のために働きました。
「output_buffering」を ini_set(...) でオフにできませんでした。php.iniで直接オンにする必要がありました。phpinfo() をオフにすると、その設定が「値なし」と表示されます。これは正常ですか? .
使用する正しい関数はflush()
.
<html>
<body>
<p>
Hello! I am waiting for the next message...<br />
<?php flush(); sleep(5); ?>
I am the next message!<br />
<?php flush(); sleep(5); ?>
And I am the last message. Good bye.
</p>
</body>
</html>
IE には「問題」があり、フラッシュされたコンテンツが 256 バイト以上の場合にのみ出力されるため、ページの最初の部分は 256 バイト以上である必要があることに注意してください。
ウイルス対策ソフトウェアが出力フラッシュを妨害している可能性もあります。私の場合、承認済みのソリューションを使用していたにもかかわらず、Kaspersky Anti-Virus 2013 はブラウザーに送信する前にデータ チャンクを保持していました。
これを試して:
while (@ob_end_flush());
ob_implicit_flush(true);
echo "first line visible to the browser";
echo "<br />";
sleep(5);
echo "second line visible to the browser after 5 secs";
この方法では、現在のスクリプトの出力バッファーを実際に無効にしていることに注意してください。ob_start() で再度有効にできると思います(よくわかりません)。
重要なことは、上記のように出力バッファを無効にすると、関数を使用して php スクリプトをリダイレクトできなくなることです。これはheader()
、php がスクリプト実行ごとに http ヘッダーを 1 回しか送信できないためです。ただし、JavaScript を使用してリダイレクトすることはできます。それに関しては、phpスクリプトに次の行をエコーさせてください:
echo '<script type="text/javascript">';
echo 'window.location.href="'.$url.'";';
echo '</script>';
echo '<noscript>';
echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
echo '</noscript>';
exit;
Dreamhost などの特定の共有ホスティング サイトを使用している場合は、別のルートを経由しない限り、PHP 出力バッファリングをまったく無効にできないことに注意してください。
出力バッファ キャッシュの変更 PHP FastCGI を使用している場合、PHP 関数の flush()、ob_flush()、および ob_implicit_flush() は期待どおりに機能しません。デフォルトでは、出力は PHP よりも高いレベルでバッファリングされます (具体的には、形式/機能が mod_gzip に似ているApache モジュール mod_deflateによって)。
バッファリングされていない出力が必要な場合は、(FastCGI の代わりに) CGI を使用するか、サイトで mod_deflate を無効 にするようサポートに連絡する必要があります。
https://help.dreamhost.com/hc/en-us/articles/214202188-PHP-概要