- <?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緩存實現
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.