PHP 缓存实现代码及详细注释
前端之家收集整理的这篇文章主要介绍了
PHP 缓存实现代码及详细注释,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
<div class="codetitle"><a style="CURSOR: pointer" data="7505" class="copybut" id="copybut7505" onclick="doCopy('code7505')"> 代码如下:
<div class="codebody" id="code7505">
class CacheException extends Exception {}
/
缓存抽象类
/
abstract class Cache_Abstract {
/ 读缓存变量
@param string $key 缓存下标
@return mixed
*/
abstract public function fetch($key); /
缓存变量
@param string $key 缓存变量下标
@param string $value 缓存变量的值
@return bool
/
abstract public function store($key,$value); / 删除缓存变量
@param string $key 缓存下标
@return Cache_Abstract
*/
abstract public function delete($key); /
清(删)除所有缓存
@return Cache_Abstract
/
abstract public function clear(); / 锁定缓存变量
@param string $key 缓存下标
@return Cache_Abstract
*/
abstract public function lock($key);
/
缓存变量解锁
@param string $key 缓存下标
@return Cache_Abstract
*/
abstract public function unlock($key);
/*
取得缓存变量是否被锁定
@param string $key 缓存下标
@return bool
/
abstract public function isLocked($key);
/ 确保不是锁定状态
最多做$tries次睡眠等待解锁,超时则跳过并解锁
@param string $key 缓存下标
*/
public function checkLock($key) {
if (!$this->isLocked($key)) {
return $this;
} $tries = 10;
$count = 0;
do {
usleep(200);
$count ++;
} while ($count <= $tries && $this->isLocked($key)); // 最多做十次睡眠等待解锁,超时则跳过并解锁
$this->isLocked($key) && $this->unlock($key); return $this;
}
} /
APC扩展缓存实现
@category Mjie
@package Cache
@author 流水孟春
@copyright Copyright (c) 2008- <cmpan(at)qq.com>
@license New BSD License
@version $Id: Cache/Apc.PHP 版本号 2010-04-18 23:02 cmpan $
/
class Cache_Apc extends Cache_Abstract { protected $_prefix = 'cache.mjie.net'; public function __construct() {
if (!function_exists('apc_cache_info')) {
throw new CacheException('apc extension didn\'t installed');
}
} / 保存缓存变量
@param string $key
@param mixed $value
@return bool
/
public function store($key,$value) {
return apc_store($this->_storageKey($key),$value);
} /
读取缓存
@param string $key
@return mixed
*/
public function fetch($key) {
return apc_fetch($this->_storageKey($key));
} /
清除缓存
@return Cache_Apc
/
public function clear() {
apc_clear_cache();
return $this;
} /
删除缓存单元
@return Cache_Apc
/
public function delete($key) {
apc_delete($this->_storageKey($key));
return $this;
} /*
缓存单元是否被锁定
@param string $key
@return bool
/
public function isLocked($key) {
if ((apc_fetch($this->_storageKey($key) . '.lock')) === false) {
return false;
} return true;
} / 锁定缓存单元
@param string $key
@return Cache_Apc
*/
public function lock($key) {
apc_store($this->_storageKey($key) . '.lock','',5);
return $this;
} /
缓存单元解锁
@param string $key
@return Cache_Apc
*/
public function unlock($key) {
apc_delete($this->_storageKey($key) . '.lock');
return $this;
} /*
完整缓存名
@param string $key
@return string
/
private function _storageKey($key) {
return $this->prefix . '' . $key;
}
}
/ 文件缓存实现
@category Mjie
@package Cache
@author 流水孟春
@copyright Copyright (c) 2008- <cmpan(at)qq.com>
@license New BSD License
@version $Id: Cache/File.PHP 版本号 2010-04-18 16:46 cmpan $
/
class Cache_File extends Cache_Abstract { protected $_cachesDir = 'cache'; public function __construct() {
if (defined('DATA_DIR')) {
$this->_setCacheDir(DATA_DIR . '/cache');
}
} /
获取缓存文件
@param string $key
@return string
*/
protected function _getCacheFile($key) {
return $this->_cachesDir . '/' . substr($key,2) . '/' . $key . '.PHP';
}
/
读取缓存变量
为防止信息泄露,缓存文件格式为PHP文件,并以"<?php exit;?>"开头
@param string $key 缓存下标
@return mixed
/
public function fetch($key) {
$cacheFile = self::_getCacheFile($key);
if (file_exists($cacheFile) && is_readable($cacheFile)) {
return unserialize(@file_get_contents($cacheFile,false,NULL,13));
}
return false;
}
/
缓存变量
为防止信息泄露,缓存文件格式为PHP文件,并以"<?php exit;?>"开头
@param string $key 缓存变量下标
@param string $value 缓存变量的值
@return bool
*/
public function store($key,$value) {
$cacheFile = self::_getCacheFile($key);
$cacheDir = dirname($cacheFile);
if(!is_dir($cacheDir)) {
if(mkdir($cacheDir" target="_blank">!@mkdir($cacheDir,0755,true)) {
throw new CacheException("Could not make cache directory");
}
}
return @file_put_contents($cacheFile,'<?php exit;?>' . serialize($value));
}
/ 删除缓存变量
@param string $key 缓存下标
@return Cache_File
*/
public function delete($key) {
if(emptyempty($key)) {
throw new CacheException("Missing argument 1 for Cache_File::delete()");
} $cacheFile = self::_getCacheFile($key);
if($cacheFile" target="_blank">!@unlink($cacheFile)) {
throw new CacheException("Cache file could not be deleted");
}
return $this;
}
/
缓存单元是否已经锁定
@param string $key
@return bool
*/
public function isLocked($key) {
$cacheFile = self::_getCacheFile($key);
clearstatcache();
return file_exists($cacheFile . '.lock');
}
/*
锁定
@param string $key
@return Cache_File
/
public function lock($key) {
$cacheFile = self::_getCacheFile($key);
$cacheDir = dirname($cacheFile);
if(!is_dir($cacheDir)) {
if(mkdir($cacheDir" target="_blank">!@mkdir($cacheDir,true)) {
if(!is_dir($cacheDir)) {
throw new CacheException("Could not make cache directory");
}
}
}
// 设定缓存锁文件的访问和修改时间
@touch($cacheFile . '.lock');
return $this;
} / 解锁
@param string $key
@return Cache_File
*/
public function unlock($key) {
$cacheFile = self::_getCacheFile($key);
@unlink($cacheFile . '.lock');
return $this;
}
/
设置文件缓存目录
@param string $dir
@return Cache_File
/
protected function _setCacheDir($dir) {
$this->_cachesDir = rtrim(str_replace('\','/',trim($dir)),'/');
clearstatcache();
if(!is_dir($this->_cachesDir)) {
mkdir($this->_cachesDir,true);
}
//
return $this;
} / 清空所有缓存
@return Cache_File
/
public function clear() {
// 遍历目录清除缓存
$cacheDir = $this->_cachesDir;
$d = dir($cacheDir);
while(false !== ($entry = $d->read())) {
if('.' == $entry[0]) {
continue;
} $cacheEntry = $cacheDir . '/' . $entry;
if(is_file($cacheEntry)) {
@unlink($cacheEntry);
} elseif(is_dir($cacheEntry)) {
// 缓存
文件夹有两级
$d2 = dir($cacheEntry);
while(false !== ($entry = $d2->read())) {
if('.' == $entry[0]) {
continue;
} $cacheEntry .= '/' . $entry;
if(is_file($cacheEntry)) {
@unlink($cacheEntry);
}
}
$d2->close();
}
}
$d->close(); return $this;
}
}
/
缓存单元的数据结构
array(
'time' => time(),// 缓存写入时的时间戳
'expire' => $expire,// 缓存过期时间
'valid' => true,// 缓存是否有效
'data' => $value // 缓存的值
);
/
final class Cache {
/ 缓存过期时间长度(s)
@var int
/
private $_expire = 3600;
/
缓存处理类
@var Cache_Abstract
/
private $_storage = null;
/ @return Cache
/
static public function createCache($cacheClass = 'Cache_File') {
return new self($cacheClass);
}
private function __construct($cacheClass) {
$this->_storage = new $cacheClass();
}
/
设置缓存
@param string $key
@param mixed $value
@param int $expire
/
public function set($key,$value,$expire = false) {
if (!$expire) {
$expire = $this->_expire;
} $this->_storage->checkLock($key); $data = array('time' => time(),'expire' => $expire,'valid' => true,'data' => $value);
$this->_storage->lock($key); try {
$this->_storage->store($key,$data);
$this->_storage->unlock($key);
} catch (CacheException $e) {
$this->_storage->unlock($key);
throw $e;
}
}
/ 读取缓存
@param string $key
@return mixed
*/
public function get($key) {
$data = $this->fetch($key);
if ($data && $data['valid'] && !$data['isExpired']) {
return $data['data'];
} return false;
}
/
读缓存,包括过期的和无效的,取得完整的存贮结构
@param string $key
/
public function fetch($key) {
$this->_storage->checkLock($key);
$data = $this->_storage->fetch($key);
if ($data) {
$data['isExpired'] = (time() - $data['time']) > $data['expire'] ? true : false;
return $data;
} return false;
}
/ 删除缓存
@param string $key
/
public function delete($key) {
$this->_storage->checkLock($key)
->lock($key)
->delete($key)
->unlock($key);
} public function clear() {
$this->_storage->clear();
}
/
把缓存设为无效
@param string $key
/
public function setInvalidate($key) {
$this->_storage->checkLock($key)
->lock($key);
try {
$data = $this->_storage->fetch($key);
if ($data) {
$data['valid'] = false;
$this->_storage->store($key,$data);
}
$this->_storage->unlock($key);
} catch (CacheException $e) {
$this->_storage->unlock($key);
throw $e;
}
} / 设置缓存过期时间(s)
@param int $expire
/
public function setExpire($expire) {
$this->_expire = (int) $expire;
return $this;
}
}