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

PHP 簡易頁面快取類實作:檔案快取減輕資料庫壓力

     編輯:PHP 綜合知識

頁面快取是提升 PHP 應用效能最直接的手段。本文提供一個輕量、實用的檔案快取類,支援自動過期、參數化快取鍵、手動清除。

Cache 類別完整程式碼

<?php
/**
 * 簡易檔案快取類
 * 常數需預先定義:
 * define('_CachePath_', '/path/to/cache/');   // 快取目錄(需可寫)
 * define('_CacheEnable_', true);              // 是否啟用
 * define('_ReCacheTime_', 3600);              // 自動重建間隔(秒),0=不自動重建
 */
class Cache {
    private $cacheFile;      // 當前頁面快取檔
    private $cacheIndexFile; // 群組索引檔(記錄最後更新時間)

    public function __construct() {
        // 以 SCRIPT_NAME + _ActionVar_ 區分不同動作
        $script = str_replace(['.', '/'], '_', $_SERVER['SCRIPT_NAME']);
        $action = $_GET['_ActionVar_'] ?? 'index';
        $this->cacheIndexFile = $script . '_' . $action;

        // 具體快取檔含 REQUEST_URI 雜湊(區分不同參數)
        $this->cacheFile = $this->cacheIndexFile . '.' . md5($_SERVER['REQUEST_URI']);
    }

    /** 刪除當前頁面群組所有快取 */
    public function delete() {
        $dir = _CachePath_;
        $prefix = $this->cacheIndexFile;
        $len = strlen($prefix);
        $handle = opendir($dir);
        while (($file = readdir($handle)) !== false) {
            if (strncmp($file, $prefix, $len) === 0) {
                @unlink($dir . $file);
            }
        }
        closedir($handle);
    }

    /** 檢查快取是否存在且有效 */
    public function check() {
        if (!_CacheEnable_) return false;

        // 檢查自動重建時間
        if (_ReCacheTime_ > 0) {
            $indexFile = _CachePath_ . $this->cacheIndexFile;
            if (file_exists($indexFile)) {
                $lastUpdate = (int)@file_get_contents($indexFile);
                if (time() - $lastUpdate > _ReCacheTime_) {
                    $this->delete();
                    return false;
                }
            }
        }

        return file_exists(_CachePath_ . $this->cacheFile);
    }

    /** 讀取快取內容並輸出 */
    public function read() {
        if (!_CacheEnable_) return false;
        $file = _CachePath_ . $this->cacheFile;
        if (file_exists($file)) {
            readfile($file);
            return true;
        }
        return false;
    }

    /** 寫入快取 */
    public function write($content) {
        if (!_CacheEnable_) return false;

        $file = _CachePath_ . $this->cacheFile;
        $fp = @fopen($file, 'w');
        if (!$fp || !@fwrite($fp, $content)) {
            trigger_error('快取寫入失敗: ' . $file, E_USER_WARNING);
            return false;
        }
        fclose($fp);

        // 更新群組索引時間
        if (_ReCacheTime_ > 0) {
            $indexFile = _CachePath_ . $this->cacheIndexFile;
            @file_put_contents($indexFile, time());
        }
        return true;
    }
}
?>

使用方式

<?php
// 入口檔案或公共引入
define('_CachePath_', __DIR__ . '/cache/');
define('_CacheEnable_', true);
define('_ReCacheTime_', 3600); // 1 小時自動重建
require 'Cache.php';

$cache = new Cache();

// 快取命中:直接輸出並結束
if ($cache->check()) {
    $cache->read();
    exit;
}

// 快取未命中:開始輸出緩衝
ob_start();
ob_implicit_flush(0);
?>
<!DOCTYPE html>
<html>
<head><title>動態頁面</title></head>
<body>
    <h1>目前時間: <?= date('Y-m-d H:i:s') ?></h1>
    <p>這段內容會被快取 1 小時</p>
    <?php
    // 模擬資料庫查詢
    sleep(1);
    echo "<p>資料載入完成</p>";
    ?>
</body></html>
<?php
// 結束:取得緩衝內容並寫入快取
$content = ob_get_contents();
$cache->write($content);
ob_end_flush();
?>

核心設計解析

設計點實作方式優勢
快取鍵區分參數md5(REQUEST_URI)同腳本不同查詢字串獨立快取
群組管理索引檔記錄最後更新時間單次 delete() 清除同腳本所有參數快取
自動過期重建_ReCacheTime_ + 索引檔時間比對無需背景程式,請求驅動自動淘汰
輸出緩衝捕獲ob_start() / ob_get_contents()零侵入業務邏輯,透明快取
可關閉開關_CacheEnable_ 常數除錯/開發時一鍵停用

進階擴展建議

  • 標籤式失效:快取檔名含標籤,deleteByTag('user_123') 掃描檔名刪除
  • Redis 後端:介面相同,改用 Redis::setex()/get(),支援叢集
  • 壓縮儲存:gzencode($content, 6) 寫入,gzdecode() 讀取,節省 70% 空間
  • 片段快取:將 write/read 改為靜態方法,支援區塊級快取 Cache::fragment('sidebar', fn() => renderSidebar())

適用場景與限制

適用不適用
內容較靜態的頁面(文章、列表、首頁)高度個人化頁面(購物車、用戶儀表板)
資料庫查詢繁重的報表頁即時性要求極高(股票、聊天)
流量大、讀多寫少頻繁更新的內容

此快取類不足 100 行,零依賴,即拿即用,是中小型 PHP 專案效能優化的第一步。

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