首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

掌握 PHP 輸出控制:利用緩存與 Gzip 壓縮加速動態頁面

     編輯:PHP 綜合知識

前言:為什麼需要輸出控制?

在早期的 Web 開發中,伺服器端腳本產生的內容會立即逐行發送給瀏覽器。這不僅限制了在輸出前修改 HTTP 標頭(如設定 Cookie 或重導向)的靈活性,也錯失了對內容進行壓縮、快取等最佳化的機會。PHP 4 引入的輸出控制函數(Output Control Functions)徹底改變了這一局面,允許開發者將腳本輸出暫存於記憶體緩衝區,在適當時機再統一處理並發送。

核心輸出控制函數速查

  • ob_start():開啟輸出緩衝,後續所有輸出(echo、print、HTML 等)將導向內部緩衝區而非直接送往瀏覽器。
  • ob_get_contents():取得目前緩衝區內的字串內容。
  • ob_get_length():回傳緩衝區內容的位元組長度。
  • ob_end_clean():清空緩衝區並關閉輸出緩衝,內容不會自動輸出。
  • ob_implicit_flush(false):關閉隱含刷新,確保輸出僅在緩衝區滿或腳本結束時才發送。

實作 Gzip 壓縮輸出流程

配合 Zlib 擴展,我們可以在腳本結束前對緩衝內容進行壓縮,大幅減少傳輸體積。以下是完整實作範例:

<?php
// 1. 啟動緩衝並關閉隱含刷新
ob_start();
ob_implicit_flush(0);

// 2. 產生頁面內容(可包含大量 HTML、echo、print 等)
print("Hey this is a compressed output!");

// 3. 取得緩衝內容並關閉緩衝
$contents = ob_get_contents();
ob_end_clean();

// 4. 偵測瀏覽器是否支援 gzip/deflate
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) {
    // 發送正確的編碼標頭
    header("Content-Encoding: gzip");
    
    // Gzip 檔案標頭(ID1=0x1f, ID2=0x8b, CM=8=deflate, FLG=0, MTIME=0, XFL=0, OS=0)
    echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
    
    // 計算原始資料大小與 CRC32
    $size = strlen($contents);
    $crc  = crc32($contents);
    
    // 壓縮資料(等級 9 最高)
    $contents = gzcompress($contents, 9);
    
    // gzcompress 回傳的資料結尾包含 4 位元組的 CRC 與 4 位元組的長度,
    // 但標準 gzip 格式要求尾部為 CRC32 + ISIZE(原始長度 mod 2^32)。
    // 這裡移除 gzcompress 產生的尾部 4 字節,改由手動附加標準 CRC 與 SIZE。
    $contents = substr($contents, 0, -4);
    
    // 輸出壓縮後的資料本體
    echo $contents;
    
    // 以 little-endian 依序輸出 CRC32 與原始長度(各 4 位元組)
    function gzip_print_four_chars($val) {
        for ($i = 0; $i < 4; $i++) {
            echo chr($val % 256);
            $val = floor($val / 256);
        }
    }
    gzip_print_four_chars($crc);
    gzip_print_four_chars($size);
} else {
    // 不支援壓縮則直接輸出原始內容
    echo $contents;
}
?>

輸出緩衝的另一大用途:頁面快取

除了壓縮,輸出緩衝還能輕鬆實現頁面級快取,減少資料庫查詢與運算開銷。基本邏輯如下:

  1. 依請求 URI 產生唯一快取檔名(如 md5($_SERVER['REQUEST_URI']))。
  2. 檢查快取檔是否存在且未過期(可自訂 is_valid() 判斷)。
  3. 若快取有效,直接 readfile() 輸出;否則啟動緩衝、產生內容、寫入快取檔後再輸出。
<?php
$cache_file = '/cache/' . md5($_SERVER['REQUEST_URI']);
if (!file_exists($cache_file) || !is_valid($cache_file)) {
    ob_start();
    ob_implicit_flush(0);
    // ... 這裡執行耗時的資料庫查詢、模板渲染等 ...
    $content = ob_get_contents();
    ob_end_clean();
    file_put_contents($cache_file, $content);
}
readfile($cache_file);
?>

進階應用:XML + XSLT 動態轉換

利用輸出緩衝捕獲動態生成的 XML 內容,再搭配 Sablotron 或 libxslt 擴展進行 XSLT 轉換,即可輕鬆支援多種輸出格式(HTML、WAP、PDF 等),實現「資料與呈現分離」的架構優勢。

總結

PHP 的輸出控制函數提供了強大的介面,讓開發者能在輸出前對內容進行攔截、壓縮、快取或轉換。善用 ob_start() 搭配 gzcompress() 可顯著降低頻寬消耗並提升頁面載入速度;結合檔案快取機制則能大幅減輕伺服器負載。這些技巧在高流量、高效能要求的專案中極具實務價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved