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

PHP 文件緩存工具類:實現頁面靜態化與局部緩存

     編輯:PHP 相關知識

設計目標

輕量級文件緩存類,支援全頁緩存、局部緩存、自動過期、手動清除、目錄自動創建、URL 綁定緩存文件。

核心類:Cache

<?php
class Cache {
    private $dir;       // 緩存目錄
    private $lifetime;  // 生存秒數
    private $cacheid;   // 緩存文件完整路徑
    private $ext = '.php'; // 後綴

    public function __construct($dir = '', $lifetime = 1800) {
        if ($this->dirIsValid($dir)) {
            $this->dir = rtrim($dir, '/') . '/';
            $this->lifetime = $lifetime;
            $this->cacheid = $this->getCacheId();
        }
    }

    // 檢查緩存是否有效 (存在且未過期)
    private function isValid(): bool {
        if (!file_exists($this->cacheid)) return false;
        $mtime = @filemtime($this->cacheid);
        if (!$mtime) return false;
        return (time() - $mtime) < $this->lifetime;
    }

    // 寫入緩存
    public function write($mode = 0, $content = ''): bool {
        switch ($mode) {
            case 0: // 瀏覽器輸出緩存 (ob_get_contents)
                $content = ob_get_contents();
                break;
            case 1: // 直接傳入內容
                break;
            case 2: // 讀取本地文件 (較少用)
                $content = file_get_contents($content);
                break;
        }
        ob_end_flush(); // 發送給瀏覽器並關閉輸出緩存
        
        try {
            // 確保目錄存在
            if (!is_dir(dirname($this->cacheid))) {
                mkdir(dirname($this->cacheid), 0755, true);
            }
            return file_put_contents($this->cacheid, $content) !== false;
        } catch (Exception $e) {
            error_log('Cache write failed: ' . $e->getMessage());
            return false;
        }
    }

    // 載入緩存 (有效則直接輸出並 exit)
    public function load(): void {
        if ($this->isValid()) {
            // 方式一:require 解析 PHP 代碼 (緩存文件含 PHP 標簽)
            require_once $this->cacheid;
            // 方式二:直接輸出內容 (純 HTML)
            // echo file_get_contents($this->cacheid);
            echo '';
            exit;
        } else {
            ob_start(); // 開啟輸出緩存,準備寫入
        }
    }

    // 清除緩存
    public function clean(): bool {
        if (file_exists($this->cacheid)) {
            return @unlink($this->cacheid);
        }
        return true;
    }

    // 生成緩存文件名:MD5(URL)
    private function getCacheId(): string {
        return $this->dir . md5($this->getCurrentUrl()) . $this->ext;
    }

    // 獲取當前完整 URL
    private function getCurrentUrl(): string {
        $url = '';
        if (isset($_SERVER['REQUEST_URI'])) {
            $url = $_SERVER['REQUEST_URI'];
        } else {
            $url = $_SERVER['PHP_SELF'];
            $url .= empty($_SERVER['QUERY_STRING']) ? '' : '?' . $_SERVER['QUERY_STRING'];
        }
        return $url;
    }

    // 檢查/創建目錄
    private function dirIsValid($dir): bool {
        if (is_dir($dir)) return true;
        try {
            return mkdir($dir, 0755, true);
        } catch (Exception $e) {
            error_log('Cache dir create failed: ' . $e->getMessage());
            return false;
        }
    }
}
?>

使用模式

模式一:全頁緩存 (入口文件/控制器基類)

<?php
// 頁面最頂部
$cachedir = __DIR__ . '/cache/';
$cache = new Cache($cachedir, 300); // 5 分鐘

// 強制刷新:?cacheact=rewrite 或 ?clearCache=ok
if (($_GET['cacheact'] ?? '') !== 'rewrite' && ($_GET['clearCache'] ?? '') !== 'ok') {
    $cache->load(); // 緩存有效則直接輸出並 exit
}

// --- 以下為動態業務邏輯 ---
// 數據庫查詢、模板渲染、複雜計算...
echo "動態生成內容: " . date('H:i:s');

// 頁面底部
$cache->write(); // 首次或過期時寫入緩存
?>

模式二:局部緩存 (數據查詢結果)

<?php
function getHotArticles($limit = 10) {
    $cache = new Cache(__DIR__ . '/cache/data/', 600);
    $key = 'hot_articles_' . $limit;
    $cache->cacheid = $cache->dir . md5($key) . $cache->ext; // 手動指定 key
    
    if ($cache->isValid()) {
        return require $cache->cacheid; // 緩存文件返回數組
    }
    
    // 耗時查詢
    $data = $db->query("SELECT * FROM articles ORDER BY views DESC LIMIT $limit")->fetchAll();
    
    // 寫入緩存 (返回 PHP 數組代碼)
    $content = "";
    file_put_contents($cache->cacheid, $content);
    
    return $data;
}
?>

緩存文件示例 (模式二)

<?php return array (
  0 => array ('id' => 1, 'title' => 'PHP技巧', 'views' => 1024),
  1 => array ('id' => 2, 'title' => 'MySQL優化', 'views' => 896),
); ?>

進階功能擴展

<?php
// 1. 緩存標籤/分組清除
class TaggedCache extends Cache {
    private $tags = [];
    public function setTags(array $tags) { $this->tags = $tags; }
    public function cleanByTag($tag) {
        // 掃描目錄,解析文件頭註釋標籤,匹配則刪除
    }
}

// 2. 多級緩存:內存 (APCu/Redis) + 文件
class MultiLevelCache {
    public function get($key) {
        if ($data = apcu_fetch($key)) return $data;
        // 降級到文件...
    }
    public function set($key, $data, $ttl) {
        apcu_store($key, $data, $ttl);
        // 同步文件...
    }
}

// 3. 緩存預熱 CLI 命令
// php cli.php cache:warm /article/list /product/detail
?>

注意事項

  1. 權限:緩存目錄需 Web 進程讀寫權限 (通常 `www-data` 或 `nginx` 用戶)
  2. 緩存雪崩**:熱點數據同時過期導致 DB 壓力激增 → 隨機過期時間、互斥鎖重建
  3. 緩存穿透**:查詢不存在數據每次穿透 DB → 空結果緩存、布隆過濾器
  4. 一致性**:數據更新後主動清除相關緩存 (`$cache->clean()` 或按模式批量刪除)
  5. 文件數量**:大量緩存文件導致 inode 耗盡 → 多級子目錄 (`md5[0:2]/md5[2:4]/file`)

總結

文件緩存類構建簡單、無外部依賴、適合中小項目快速引入。核心邏輯:URL 綁定文件名、修改時間判斷過期、輸出緩存捕獲內容。生產環境建議配合 OPcache、Redis 多級緩存架構,並建立完善的緩存更新/清除策略。

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