提供一個開箱即用的全頁緩存方案,核心特性:
$_SERVER['REQUEST_URI'] 自動區分緩存文件(支持動態參數如 test.php?id=12)__FILE__)修改時間晚於緩存文件時,強制重新生成,解決代碼部署後緩存不更新的痛點ob_start)捕獲頁面輸出,無需修改業務邏輯class cache {
var $cache_dir = './cache/';
var $cache_time = 120;
var $caching = false;
var $file = '';
function __construct() {
$this->file = $this->cache_dir . urlencode($_SERVER['REQUEST_URI']);
$expired = file_exists($this->file) ? $this->check_expire() : false;
// 命中有效緩存:直接輸出並退出
if (file_exists($this->file)
&& (filemtime($this->file) + $this->cache_time) > time()
&& !$expired) {
$handle = fopen($this->file, 'r');
while ($data = fread($handle, 8192)) echo $data;
fclose($handle);
exit();
}
// 未命中或已過期:啟用緩存模式
$this->caching = true;
ob_start();
echo '<!--last modified:' . time() . '--> '; // 嵌入時間戳供失效檢測
}
function close() {
if ($this->caching) {
$data = ob_get_clean();
echo $data;
$fp = fopen($this->file, 'w');
fwrite($fp, $data);
fclose($fp);
}
}
// 檢測源文件是否更新
function check_expire() {
$fp = fopen($this->file, 'r');
preg_match('/:(\d+)-/', fread($fp, 200), $time);
$modify_time = $time[1];
fclose($fp);
return $modify_time < filemtime($_SERVER['SCRIPT_FILENAME']);
}
}
<?php
require_once 'cache.class.php';
$ch = new cache(); // 構造函數自動檢測緩存,命中則直接輸出並 exit
// 業務邏輯:查詢數據庫、渲染模板等
echo date('D M j G:i:s T Y'); // 模擬動態內容
$ch->close(); // 緩存模式下將輸出寫入文件
?>
| 機制 | 實現細節 | 作用 |
|---|---|---|
| 緩存鍵生成 | urlencode($_SERVER['REQUEST_URI']) | 不同 URL 參數生成獨立緩存文件,避免衝突 |
| 時間過期判斷 | filemtime($file) + $cache_time > time() | 基於文件修改時間的簡單 TTL 機制 |
| 源文件變更檢測 | 正則提取緩存文件頭部時間戳,對比 filemtime(__FILE__) | 代碼部署後自動失效舊緩存,無需手動清理 |
| 輸出捕獲 | ob_start() / ob_get_clean() | 非侵入式攔截輸出,業務代碼無感知 |
flock() 文件鎖或改用 Redis。preg_match('/:(\d+)-/') 依賴特定註釋格式。建議改用 serialize()/json_encode() 存儲元數據(過期時間、源文件 mtime 等)。這個緩存類以極少代碼實現了「按 URL 區分、時間過期、源文件變更自動失效」三大核心功能,非常適合中小型項目快速接入頁面級緩存。理解其原理後,可根據業務規模演進至更健壯的緩存架構。