在 PHP 中,當我們使用 echo 或 print 輸出內容時,數據並不會立即經由 TCP 傳送給瀏覽器顯示,而是先寫入 PHP 內部的輸出緩衝區。這機制在 TCP 緩衝之前建立了一個新的隊列,數據必須依次通過:echo/print → PHP buffer → TCP buffer → 瀏覽器。只有當 PHP 緩衝區寫滿、腳本結束或主動刷新時,數據才會被系統內核交給 TCP 發送給客戶端。
flush() 用於刷新 PHP 程序的輸出緩衝,將截至目前的所有輸出發送到用戶瀏覽器。但它不影響服務器或客戶端瀏覽器的緩存模式,也不會改變 PHP 本身的緩存行為。
ob_flush() 專門針對 PHP 自身的輸出緩衝(由 php.ini 中的 output_buffering 控制)。它將輸出緩衝區的內容取出並設置為「等待輸出」狀態,但不會直接發送到客戶端。因此,通常需要先呼叫 ob_flush() 再呼叫 flush(),客戶端才能即時獲得腳本輸出。
啟用 ob_implicit_flush(true) 後,每當有輸出動作(如 echo)就會立即把輸出發送到瀏覽器,省去每次手動呼叫 flush() 的麻煩。
On/Off 或整數(如 4096)。開啟時所有腳本啟用輸出緩衝控制;設為整數時,緩衝區達到該位元組數會自動刷新。關閉時 echo 即時發送;開啟時內容會緩存至腳本結束才一次發送。On/Off。設為 On 相當於每次 echo 後自動加上 flush()。<?php
// 寫法一:手動雙重刷新
ob_end_clean();
echo str_pad(" ", 256); // IE 需 256 字節才開始顯示
for ($i = 100; $i > 0; $i--) {
echo $i, '<br/>';
ob_flush();
flush();
sleep(1);
}
?>
<?php
// 寫法二:隱式刷新
ob_implicit_flush(true);
echo str_pad(" ", 256);
for ($i = 100; $i > 0; $i--) {
echo $i, '<br/>';
ob_flush(); // 僅需 ob_flush
sleep(1);
}
?>
注意:str_pad(" ", 256) 是為了滿足 IE 瀏覽器需接收 256 字節才開始渲染的特性。
flush() 不立即生效。以下示範一個簡單的檔案緩存類,利用 ob_start() 捕獲輸出並寫入靜態檔案:
<?php
class my_cache {
private $cache_time, $cache_file;
public function __construct($cache_file='index.html', $cache_time=1) {
$this->cache_file = $cache_file;
$this->cache_time = $cache_time;
}
public function cache_start() {
if ($this->cache_active()) {
include $this->cache_file;
exit;
}
ob_start();
}
private function cache_active() {
if (file_exists($this->cache_file)) {
$last_time = @filemtime($this->cache_file);
if ($this->cache_time < $last_time) return true;
unlink($this->cache_file);
}
return false;
}
private function cache_creat() {
$dirs = explode('/', $this->cache_file);
$path = '';
for ($i=0; $i<count($dirs)-1; $i++) {
$path .= $dirs[$i].'/';
if (!file_exists($path)) mkdir($path);
}
}
public function cache_end() {
$content = ob_get_contents();
$this->cache_creat();
$fp = @fopen($this->cache_file, 'w+');
fwrite($fp, $content);
ob_end_flush();
}
public function cache_clean() {
return @unlink($this->cache_file);
}
}
?>
使用方式:
<?php
include 'cache_my_class.php';
$my_cache = new my_cache('./chunge/ge/hao/index.html', 5);
$my_cache->cache_start();
echo '我愛吃橘子香蕉!<br>';
$my_cache->cache_end();
?>