欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

php中apc和文件缓存类的实现代码

程序员文章站 2022-05-01 13:56:54
...
  1. class CacheException extends Exception {}

  2. /**
  3. * 缓存抽象类
  4. */
  5. abstract class Cache_Abstract {
  6. /**
  7. * 读缓存变量
  8. *
  9. * @param string $key 缓存下标
  10. * @return mixed
  11. */
  12. abstract public function fetch($key);
  13. /**

  14. * 缓存变量
  15. *
  16. * @param string $key 缓存变量下标
  17. * @param string $value 缓存变量的值
  18. * @return bool
  19. */
  20. abstract public function store($key, $value);
  21. /**

  22. * 删除缓存变量
  23. *
  24. * @param string $key 缓存下标
  25. * @return Cache_Abstract
  26. */
  27. abstract public function delete($key);
  28. /**

  29. * 清(删)除所有缓存
  30. *
  31. * @return Cache_Abstract
  32. */
  33. abstract public function clear();
  34. /**

  35. * 锁定缓存变量
  36. *
  37. * @param string $key 缓存下标
  38. * @return Cache_Abstract
  39. */
  40. abstract public function lock($key);
  41. /**
  42. * 缓存变量解锁
  43. *
  44. * @param string $key 缓存下标
  45. * @return Cache_Abstract
  46. */
  47. abstract public function unlock($key);
  48. /**
  49. * 取得缓存变量是否被锁定
  50. *
  51. * @param string $key 缓存下标
  52. * @return bool
  53. */
  54. abstract public function isLocked($key);
  55. /**
  56. * 确保不是锁定状态
  57. * 最多做$tries次睡眠等待解锁,超时则跳过并解锁
  58. *
  59. * @param string $key 缓存下标
  60. */
  61. public function checkLock($key) {
  62. if (!$this->isLocked($key)) {
  63. return $this;
  64. }
  65. $tries = 10;
  66. $count = 0;
  67. do {
  68. usleep(200);
  69. $count ++;
  70. } while ($count isLocked($key)); // 最多做十次睡眠等待解锁,超时则跳过并解锁
  71. $this->isLocked($key) && $this->unlock($key);
  72. return $this;
  73. }
  74. }
  75. /**

  76. * APC扩展缓存实现
  77. *
  78. * @by bbs.it-home.org
  79. * @category Mjie
  80. * @package Cache
  81. * @license New BSD License
  82. * @version $Id: Cache/Apc.php 版本号 2010-04-18 23:02 cmpan $
  83. */
  84. class Cache_Apc extends Cache_Abstract {
  85. protected $_prefix = 'cache.mjie.net';

  86. public function __construct() {

  87. if (!function_exists('apc_cache_info')) {
  88. throw new CacheException('apc extension didn\'t installed');
  89. }
  90. }
  91. /**

  92. * 保存缓存变量
  93. *
  94. * @param string $key
  95. * @param mixed $value
  96. * @return bool
  97. */
  98. public function store($key, $value) {
  99. return apc_store($this->_storageKey($key), $value);
  100. }
  101. /**

  102. * 读取缓存
  103. *
  104. * @param string $key
  105. * @return mixed
  106. */
  107. public function fetch($key) {
  108. return apc_fetch($this->_storageKey($key));
  109. }
  110. /**

  111. * 清除缓存
  112. *
  113. * @return Cache_Apc
  114. */
  115. public function clear() {
  116. apc_clear_cache();
  117. return $this;
  118. }
  119. /**

  120. * 删除缓存单元
  121. *
  122. * @return Cache_Apc
  123. */
  124. public function delete($key) {
  125. apc_delete($this->_storageKey($key));
  126. return $this;
  127. }
  128. /**

  129. * 缓存单元是否被锁定
  130. *
  131. * @param string $key
  132. * @return bool
  133. */
  134. public function isLocked($key) {
  135. if ((apc_fetch($this->_storageKey($key) . '.lock')) === false) {
  136. return false;
  137. }
  138. return true;
  139. }
  140. /**

  141. * 锁定缓存单元
  142. *
  143. * @param string $key
  144. * @return Cache_Apc
  145. */
  146. public function lock($key) {
  147. apc_store($this->_storageKey($key) . '.lock', '', 5);
  148. return $this;
  149. }
  150. /**

  151. * 缓存单元解锁
  152. *
  153. * @param string $key
  154. * @return Cache_Apc
  155. */
  156. public function unlock($key) {
  157. apc_delete($this->_storageKey($key) . '.lock');
  158. return $this;
  159. }
  160. /**

  161. * 完整缓存名
  162. *
  163. * @param string $key
  164. * @return string
  165. */
  166. private function _storageKey($key) {
  167. return $this->_prefix . '_' . $key;
  168. }
  169. }
  170. /**
  171. * 文件缓存实现
  172. *
  173. * @by bbs.it-home.org
  174. * @category Mjie
  175. * @package Cache
  176. * @license New BSD License
  177. * @version $Id: Cache/File.php 版本号 2010-04-18 16:46 cmpan $
  178. */
  179. class Cache_File extends Cache_Abstract {
  180. protected $_cachesDir = 'cache';

  181. public function __construct() {

  182. if (defined('DATA_DIR')) {
  183. $this->_setCacheDir(DATA_DIR . '/cache');
  184. }
  185. }
  186. /**

  187. * 获取缓存文件
  188. *
  189. * @param string $key
  190. * @return string
  191. */
  192. protected function _getCacheFile($key) {
  193. return $this->_cachesDir . '/' . substr($key, 0, 2) . '/' . $key . '.php';
  194. }
  195. /**
  196. * 读取缓存变量
  197. * 为防止信息泄露,缓存文件格式为php文件,并以""开头
  198. *
  199. * @param string $key 缓存下标
  200. * @return mixed
  201. */
  202. public function fetch($key) {
  203. $cacheFile = self::_getCacheFile($key);
  204. if (file_exists($cacheFile) && is_readable($cacheFile)) {
  205. return unserialize(@file_get_contents($cacheFile, false, NULL, 13));
  206. }
  207. return false;
  208. }
  209. /**
  210. * 缓存变量
  211. * 为防止信息泄露,缓存文件格式为php文件,并以""开头
  212. *
  213. * @param string $key 缓存变量下标
  214. * @param string $value 缓存变量的值
  215. * @return bool
  216. */
  217. public function store($key, $value) {
  218. $cacheFile = self::_getCacheFile($key);
  219. $cacheDir = dirname($cacheFile);
  220. if(!is_dir($cacheDir)) {
  221. if([url=mailto:!@mkdir($cacheDir]!@mkdir($cacheDir[/url], 0755, true)) {
  222. throw new CacheException("Could not make cache directory");
  223. }
  224. }
  225. return @file_put_contents($cacheFile, '' . serialize($value));
  226. }
  227. /**
  228. * 删除缓存变量
  229. *
  230. * @param string $key 缓存下标
  231. * @return Cache_File
  232. */
  233. public function delete($key) {
  234. if(empty($key)) {
  235. throw new CacheException("Missing argument 1 for Cache_File::delete()");
  236. }
  237. $cacheFile = self::_getCacheFile($key);
  238. if([url=mailto:!@unlink($cacheFile]!@unlink($cacheFile[/url])) {
  239. throw new CacheException("Cache file could not be deleted");
  240. }
  241. return $this;
  242. }
  243. /**
  244. * 缓存单元是否已经锁定
  245. *
  246. * @param string $key
  247. * @return bool
  248. */
  249. public function isLocked($key) {
  250. $cacheFile = self::_getCacheFile($key);
  251. clearstatcache();
  252. return file_exists($cacheFile . '.lock');
  253. }
  254. /**
  255. * 锁定
  256. *
  257. * @param string $key
  258. * @return Cache_File
  259. */
  260. public function lock($key) {
  261. $cacheFile = self::_getCacheFile($key);
  262. $cacheDir = dirname($cacheFile);
  263. if(!is_dir($cacheDir)) {
  264. if([url=mailto:!@mkdir($cacheDir]!@mkdir($cacheDir[/url], 0755, true)) {
  265. if(!is_dir($cacheDir)) {
  266. throw new CacheException("Could not make cache directory");
  267. }
  268. }
  269. }
  270. // 设定缓存锁文件的访问和修改时间
  271. @touch($cacheFile . '.lock');
  272. return $this;
  273. }
  274. /**
  275. * 解锁
  276. *
  277. * @param string $key
  278. * @return Cache_File
  279. */
  280. public function unlock($key) {
  281. $cacheFile = self::_getCacheFile($key);
  282. @unlink($cacheFile . '.lock');
  283. return $this;
  284. }
  285. /**
  286. * 设置文件缓存目录
  287. * @param string $dir
  288. * @return Cache_File
  289. */
  290. protected function _setCacheDir($dir) {
  291. $this->_cachesDir = rtrim(str_replace('\\', '/', trim($dir)), '/');
  292. clearstatcache();
  293. if(!is_dir($this->_cachesDir)) {
  294. mkdir($this->_cachesDir, 0755, true);
  295. }
  296. //
  297. return $this;
  298. }
  299. /**
  300. * 清空所有缓存
  301. *
  302. * @return Cache_File
  303. */
  304. public function clear() {
  305. // 遍历目录清除缓存
  306. $cacheDir = $this->_cachesDir;
  307. $d = dir($cacheDir);
  308. while(false !== ($entry = $d->read())) {
  309. if('.' == $entry[0]) {
  310. continue;
  311. }
  312. $cacheEntry = $cacheDir . '/' . $entry;
  313. if(is_file($cacheEntry)) {
  314. @unlink($cacheEntry);
  315. } elseif(is_dir($cacheEntry)) {
  316. // 缓存文件夹有两级
  317. $d2 = dir($cacheEntry);
  318. while(false !== ($entry = $d2->read())) {
  319. if('.' == $entry[0]) {
  320. continue;
  321. }
  322. $cacheEntry .= '/' . $entry;
  323. if(is_file($cacheEntry)) {
  324. @unlink($cacheEntry);
  325. }
  326. }
  327. $d2->close();
  328. }
  329. }
  330. $d->close();
  331. return $this;
  332. }
  333. }
  334. /**
  335. * 缓存单元的数据结构
  336. * array(
  337. * 'time' => time(), // 缓存写入时的时间戳
  338. * 'expire' => $expire, // 缓存过期时间
  339. * 'valid' => true, // 缓存是否有效
  340. * 'data' => $value // 缓存的值
  341. * );
  342. */
  343. final class Cache {
  344. /**
  345. * 缓存过期时间长度(s)
  346. *
  347. * @var int
  348. */
  349. private $_expire = 3600;
  350. /**
  351. * 缓存处理类
  352. *
  353. * @var Cache_Abstract
  354. */
  355. private $_storage = null;
  356. /**
  357. * @return Cache
  358. */
  359. static public function createCache($cacheClass = 'Cache_File') {
  360. return new self($cacheClass);
  361. }
  362. private function __construct($cacheClass) {
  363. $this->_storage = new $cacheClass();
  364. }
  365. /**
  366. * 设置缓存
  367. *
  368. * @param string $key
  369. * @param mixed $value
  370. * @param int $expire
  371. */
  372. public function set($key, $value, $expire = false) {
  373. if (!$expire) {
  374. $expire = $this->_expire;
  375. }
  376. $this->_storage->checkLock($key);
  377. $data = array('time' => time(), 'expire' => $expire, 'valid' => true, 'data' => $value);
  378. $this->_storage->lock($key);
  379. try {
  380. $this->_storage->store($key, $data);
  381. $this->_storage->unlock($key);
  382. } catch (CacheException $e) {
  383. $this->_storage->unlock($key);
  384. throw $e;
  385. }
  386. }
  387. /**
  388. * 读取缓存
  389. *
  390. * @param string $key
  391. * @return mixed
  392. */
  393. public function get($key) {
  394. $data = $this->fetch($key);
  395. if ($data && $data['valid'] && !$data['isExpired']) {
  396. return $data['data'];
  397. }
  398. return false;
  399. }
  400. /**
  401. * 读缓存,包括过期的和无效的,取得完整的存贮结构
  402. *
  403. * @param string $key
  404. */
  405. public function fetch($key) {
  406. $this->_storage->checkLock($key);
  407. $data = $this->_storage->fetch($key);
  408. if ($data) {
  409. $data['isExpired'] = (time() - $data['time']) > $data['expire'] ? true : false;
  410. return $data;
  411. }
  412. return false;
  413. }
  414. /**
  415. * 删除缓存
  416. *
  417. * @param string $key
  418. */
  419. public function delete($key) {
  420. $this->_storage->checkLock($key)
  421. ->lock($key)
  422. ->delete($key)
  423. ->unlock($key);
  424. }
  425. public function clear() {

  426. $this->_storage->clear();
  427. }
  428. /**
  429. * 把缓存设为无效
  430. *
  431. * @param string $key
  432. */
  433. public function setInvalidate($key) {
  434. $this->_storage->checkLock($key)
  435. ->lock($key);
  436. try {
  437. $data = $this->_storage->fetch($key);
  438. if ($data) {
  439. $data['valid'] = false;
  440. $this->_storage->store($key, $data);
  441. }
  442. $this->_storage->unlock($key);
  443. } catch (CacheException $e) {
  444. $this->_storage->unlock($key);
  445. throw $e;
  446. }
  447. }
  448. /**

  449. * 设置缓存过期时间(s)
  450. *
  451. * @param int $expire
  452. */
  453. public function setExpire($expire) {
  454. $this->_expire = (int) $expire;
  455. return $this;
  456. }
  457. }
  458. ?>
复制代码