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

PHP 微信開發 Access Token 本地檔案快取類實作:set/get/remove 三大操作與過期自動清理

     編輯:PHP 綜合知識

應用場景

微信 `access_token` 有效期 7200 秒,頻繁請求會觸發頻率限制。無框架環境下需自行實作快取儲存,本類採用 JSON 檔案儲存,支援多鍵值、TTL 過期自動清理。

Cache 類別完整碼

<?php
class Cache {
    public $cacheFile = "cache.json";
    public $dir = "./cache/";
    
    /** 設定快取 */
    public function setCache($name, $val, $expires_time) {
        $file = $this->hasFile();
        $str = file_get_contents($file);
        $arr = $str ? json_decode($str, true) : [];
        
        if (empty($val)) {
            unset($arr[$name]); // 值為空視為刪除
        } else {
            $arr[$name] = [
                'value' => $val,
                'expires_time' => $expires_time, // TTL 秒數
                'add_time' => time(),            // 寫入時間戳
            ];
        }
        
        file_put_contents($file, json_encode($arr), LOCK_EX);
    }
    
    /** 讀取快取 */
    public function getCache($name) {
        $file = $this->hasFile();
        $str = file_get_contents($file);
        $allArr = $str ? json_decode($str, true) : [];
        
        if (!isset($allArr[$name])) return false;
        
        $item = $allArr[$name];
        // 過期檢查:當前時間 > 寫入時間 + TTL
        if (time() > ($item['add_time'] + $item['expires_time'])) {
            $this->removeCache($name);
            return false;
        }
        
        return $item['value'];
    }
    
    /** 刪除快取 */
    public function removeCache($name) {
        $this->setCache($name, '', 0);
    }
    
    /** 確保快取檔案存在 */
    private function hasFile() {
        if (!is_dir($this->dir)) {
            mkdir($this->dir, 0755, true);
        }
        $file = $this->dir . $this->cacheFile;
        if (!file_exists($file)) {
            touch($file);
        }
        return $file;
    }
}
?>

使用範例

<?php
$cache = new Cache();
$cache->dir = "../cache/"; // 自訂快取目錄

// 寫入 access_token (有效期 7000 秒,預留 200 秒緩衝)
$cache->setCache('wx_access_token', 'ACCESS_TOKEN_STRING', 7000);

// 讀取
$token = $cache->getCache('wx_access_token');
if ($token === false) {
    // 快取過期/不存在 → 向微信 API 請求新 token
    $token = requestNewAccessToken();
    $cache->setCache('wx_access_token', $token, 7000);
}
echo "Current Token: $token";

// 手動刪除
$cache->removeCache('wx_access_token');
?>

進階優化建議

問題解決方案
高併發讀寫衝突`file_put_contents(..., LOCK_EX)` 已加獨佔鎖;極高併發建議改用 Redis/Memcached
檔案過大影響效能定期清理過期項目;或分檔儲存 (每鍵一檔)
多伺服器共享檔案系統不支援共享,必須用 Redis/資料庫集中快取
資料結構擴充支援標籤/分組、序列化物件、壓縮長字串
效能監控記錄 hit/miss 率、讀寫延遲,接入 Prometheus

微信 Access Token 專用快取策略

<?php
class WxTokenCache extends Cache {
    const KEY = 'wx_access_token';
    const BUFFER = 200; // 提前 200 秒刷新
    
    public function getToken() {
        $token = $this->getCache(self::KEY);
        if ($token !== false) return $token;
        
        // 雙重檢查鎖防止併發重複請求
        $lockKey = self::KEY . '_lock';
        if ($this->getCache($lockKey)) {
            sleep(1); // 等待其他進程刷新
            return $this->getCache(self::KEY);
        }
        
        $this->setCache($lockKey, '1', 10); // 10 秒鎖
        $token = $this->requestTokenFromWx();
        $this->setCache(self::KEY, $token, 7200 - self::BUFFER);
        $this->removeCache($lockKey);
        
        return $token;
    }
    
    private function requestTokenFromWx() {
        // 實際調用微信 API 邏輯
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
        $result = json_decode(file_get_contents($url), true);
        return $result['access_token'] ?? '';
    }
}
?>

替代方案:APCu 共享記憶體快取 (單機高效能)

<?php
if (extension_loaded('apcu')) {
    apcu_store('wx_access_token', $token, 7000);
    $token = apcu_fetch('wx_access_token');
    apcu_delete('wx_access_token');
}
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved