- <?php
- 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 , 0, 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 , 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 ( empty empty ( $key )) {
- throw new CacheException( "Missing argument 1 for Cache_File::delete()" );
- }
- $cacheFile = self::_getCacheFile( $key );
- if (!@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 , 0755, 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, 0755, 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 ;
- }
- }
PHP缓存实现
最新推荐文章于 2024-08-15 15:00:52 发布