全站靜態化是高併發、SEO 友好、減輕數據庫壓力的經典架構。PHP 通過 ob_start() 系列函數捕獲輸出,寫入靜態文件,配合修改時間判斷實現增量更新。本文提供從基礎原理到生產級實現的完整方案。
| 函數 | 作用 | 典型流程 |
|---|---|---|
ob_start() | 開啟緩衝,後續輸出(echo/HTML)暫存內存 | 腳本最開頭調用 |
ob_get_contents() | 獲取緩衝區內容字符串 | 業務邏輯結束前調用 |
ob_end_clean() | 清空緩衝並關閉(不輸出到瀏覽器) | 寫入文件前調用 |
ob_end_flush() | 輸出緩衝內容到瀏覽器並關閉 | 直接響應場景 |
ob_get_length() | 獲取緩衝區字節長度 | 調試/監控 |
<?php
// 1. 啟動緩衡
ob_start();
// 2. 業務邏輯 + 模板輸出
$articles = $db->query("SELECT * FROM articles WHERE status=1 ORDER BY id DESC LIMIT 10");
include 'template/list.php'; // 包含 HTML + PHP 混合模板
// 3. 獲取內容並寫入靜態文件
$html = ob_get_contents();
ob_end_clean();
$staticFile = __DIR__ . '/static/list.html';
file_put_contents($staticFile, $html);
// 4. 可選:直接輸出給當前請求
echo $html;
?>
<?php
$staticFile = __DIR__ . '/static/article_123.html';
$ttl = 300; // 緩存壽命 5 分鐘
// 1. 靜態文件存在且未過期 → 直接輸出(最快路徑)
if (file_exists($staticFile) && (time() - filemtime($staticFile) < $ttl)) {
// 可選:發送 Last-Modified / ETag 支持瀏覽器緩存
header('Content-Type: text/html; charset=UTF-8');
readfile($staticFile);
exit;
}
// 2. 否則重新生成
ob_start();
// ... 業務邏輯查詢數據庫、渲染模板 ...
$html = ob_get_contents();
ob_end_clean();
// 3. 原子寫入(避免並發讀到半寫文件)
$tmpFile = $staticFile . '.tmp.' . mt_rand();
file_put_contents($tmpFile, $html);
rename($tmpFile, $staticFile); // rename 是原子操作
// 4. 輸出
echo $html;
?>
rename() 在同一文件系統下是原子的,防止高併發讀到損壞文件article_{id}.html),支持精準失效unlink($staticFile) 刪除對應靜態文件Cache-Control 頭實現邊緣緩存| 適用 | 不適用 |
|---|---|
| 內容型站點(新聞、博客、文檔、商品詳情) | 高度個性化頁面(用戶儀表盤、購物車、實時聊天) |
| 讀多寫少、數據變更可控 | 每次請求數據皆不同(抽獎、實時價格、個性化推薦) |
| SEO 關鍵頁面 | 涉及敏感權限、CSRF Token 強依賴的表單頁 |
用戶表 3 條記錄,Apache + PHP 7.4: 動態查詢平均耗時:0.000804 秒 靜態文件讀取平均耗時:0.000047 秒 提升約 17 倍 大數據量/復雜查詢下差距更明顯(動態 50-200ms vs 靜態 0.5-2ms)
架構建議:現代項目推薦「動態渲染 + Varnish/Nginx FastCGI Cache / Cloudflare」替代純文件靜態化,兼具動態靈活性與靜態性能,運維更簡單。