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

PHP 檔案快取類原理與實作:靜態頁面生成、自動清理過期檔案

     編輯:PHP 相關知識

核心原理

  1. 依請求 URI 產生唯一快取檔名(MD5)
  2. 檢查快取檔是否存在且未過期 → 直接輸出內容並結束腳本
  3. 否則啟動輸出緩衝,註冊關閉回調函式寫入快取
  4. 非 GET 請求(POST/PUT/DELETE)自動刪除對應快取
  5. 定期清理過期快取檔案

完整實作

<?php
// cache.php - 放置於專案入口檔案最開頭 require_once
define('CACHE_ROOT', __DIR__ . '/cache');
define('CACHE_LIFETIME', 1800); // 秒
define('CACHE_EXT', '.html');

$uri = $_SERVER['REQUEST_URI'];
$cacheName = md5($uri) . CACHE_EXT;
$cacheDir = CACHE_ROOT . DIRECTORY_SEPARATOR . $cacheName[0];
$cacheFile = $cacheDir . DIRECTORY_SEPARATOR . $cacheName;

// 僅快取 GET 請求
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    // 命中且未過期
    if (is_file($cacheFile) && (time() - filemtime($cacheFile) < CACHE_LIFETIME)) {
        readfile($cacheFile);
        exit;
    }
    
    // 建立目錄
    if (!is_dir($cacheDir)) {
        mkdir($cacheDir, 0755, true);
    }
    
    // 關閉回調寫入快取
    function writeCache($content) {
        global $cacheFile;
        $fp = fopen($cacheFile, 'wb');
        fwrite($fp, $content);
        fclose($fp);
        @chmod($cacheFile, 0644);
        
        // 可選:同步清理過期檔案
        // cleanOldCache();
        return $content;
    }
    ob_start('writeCache');
} else {
    // 非 GET 請求刪除快取
    if (is_file($cacheFile)) @unlink($cacheFile);
}

function cleanOldCache() {
    $dir = new RecursiveDirectoryIterator(CACHE_ROOT);
    $iter = new RecursiveIteratorIterator($dir);
    foreach ($iter as $file) {
        if ($file->isFile() && $file->getExtension() === 'html') {
            if (time() - $file->getMTime() > CACHE_LIFETIME) {
                @unlink($file->getPathname());
            }
        }
    }
}
?>

使用方式

<?php
// index.php
require_once 'cache.php';
// 後續正常業務邏輯
echo 'Hello World'; // 將被快取
?>

進階擴充

  • 分組快取:依功能模組建立子目錄,支援整組失效
  • 標籤快取:維護 tag -> [cache_files] 對應,精準清理
  • 記憶體快取:搭配 APCu/Redis 存儲熱點資料,檔案快取作為二級
  • 壓縮輸出:ob_start(function($c) { return gzencode($c, 9); }) 並發送 Content-Encoding: gzip

注意事項

  • 動態內容(用戶資訊、購物車、CSRF Token)不可快取,需採用片段快取或 JS 渲染
  • 快取目錄需設定正確權限,避免權限錯誤導致寫入失敗
  • 高併發下可能產生「快取擊穿」,建議加入鎖機制或使用 Redis 原子操作
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved