自己用的PHP緩存類,自己PHP緩存類
<?php
/**
* 緩存類,實現數據,輸出緩存
* @author ZhouHr 2012-11-09 http://www.ketann.com
* @copyright version 0.1
*/
class Cache
{
private static $_instance;
protected $_cacheId = null;
const CLEANING_MODE_ALL = 'all';
const CLEANING_MODE_OLD = 'old';
protected $_options = array(
'cache_dir' => null, //數據緩存目錄
'life_time' => 7200, //緩存時間
'page_dir' => null, //文本緩存目錄
'cache_prefix' => 'cache_' //緩存前綴
);
private function __construct(){}
//創建__clone方法防止對象被復制克隆
private function __clone(){}
/**
* 取緩存對象,如果存在直接返回,如果不存在實例化本身
* @return object cache
*/
public static function getInstance(){
if(! self::$_instance){
self::$_instance = new self();
}
return self::$_instance;
}
/**
* 設置緩存參數集
* @param array $options 要設置的緩存參數集
*/
public function setOptions($options = array()){
while (list($name, $value) = each($options)) {
$this->setOption($name, $value);
}
}
/**
* 取得當前緩存參數,如果$name為空返回全部參數,否則返回該參數值
* @param string $name 要返回的參數名稱
* @return string or array $option;
*/
public function getOption($name = null){
if(null === $name)
return $this->_options;
if (!is_string($name)) {
throwException("不正確的參數名稱 : $name");
}
if (array_key_exists($name, $this->_options)){
return $this->_options[$name];
}
}
/**
* 設置緩存參數
* @param array $options 要設置的緩存參數
*/
protected function setOption($name, $value){
if (!is_string($name)) {
throwException("不正確的參數名稱 : $name");
}
$name = strtolower($name);
if (array_key_exists($name, $this->getOption())){
$this->_options[$name] = $value;
}
if ($this->_options['cache_dir'] === null) {
$this->setOption('cache_dir', $this->getTmpDir() . DIRECTORY_SEPARATOR);
}
if ($this->_options['page_dir'] === null) {
$this->setOption('page_dir', $this->getTmpDir() . DIRECTORY_SEPARATOR);
}
}
/**
* 讀取數據緩存,如果不存在或過期,返回false
* @param string $id 緩存ID
* @return false or data
*/
public function load($id){
$this->_cacheId = $id;
$file = $this->getOption('cache_dir') . $this->getOption('cache_prefix') . $this->_cacheId;
if (@filemtime($file) >= time()){
return unserialize(file_get_contents($file));
} else {
@unlink($file);
return false;
}
}
/**
* 保存數據緩存,並設置緩存過期時間
* @param array or string $data 要緩存的數據
* @param int $lifeTime 緩存過期時間
*/
public function save($data, $lifeTime = null){
if(null !== $lifeTime)
$this->setOption('life_time', $lifeTime);
$file = $this->getOption('cache_dir') . $this->getOption('cache_prefix') . $this->_cacheId;
$data = serialize($data);
@file_put_contents($file, $data);
@chmod($file, 0777);
@touch($file, time() + $this->getOption('life_time']));
}
/**
* 讀取輸出緩存,如果不存在或緩存過期將重新開啟輸出緩存
* @param string $id 緩存ID
*/
public function start($id){
$this->_cacheId = $id;
$file = $this->getOption('page_dir') . $this->getOption('cache_prefix') . $this->_cacheId;
if (@filemtime($file) >= time()){
return file_get_contents($file);
} else {
@unlink($file);
ob_start();
return false;
}
}
/**
* 刪除指定ID緩存
* @param string $id 緩存ID
*/
public function remove($id){
$this->_cacheId = $id;
//刪除附合條件的數據緩存
$file = $this->getOption('cache_dir') . $this->getOption('cache_prefix') . $this->_cacheId;
@unlink($file);
//刪除附合條件的輸出緩存
$file = $this->getOption('page_dir') . $this->getOption('cache_prefix') . $this->_cacheId;
@unlink($file);
}
/**
* 保存輸出緩存,並設置緩存過期時間
* @param int $lifeTime 緩存過期時間
*/
public function end($lifeTime = null){
if(null !== $lifeTime)
$this->setOption('life_time', $lifeTime);
$file = $this->getOption('page_dir') . $this->getOption('cache_prefix') . $this->_cacheId;
$data = ob_get_contents();
ob_end_clean();
@file_put_contents($file, $data);
@chmod($file, 0777);
@touch($file, time() + $this->getOption('life_time']));
}
/**
* 根據參數清除相應緩存
* @param string $mode 緩存類型,包括(CLEANING_MODE_ALL:所有緩存, CLEANING_MODE_OLD: 過期緩存)
*/
public function clear($mode = CLEANING_MODE_OLD){
$dirs = array('cache_dir', 'page_dir');
foreach($dirs as $value){
if(null != $this->getOption($value)){
$files = scandir($this->getOption($value));
switch ($mode) {
case CLEANING_MODE_ALL:
default:
foreach ($files as $val){
@unlink($this->getOption($value) . $val);
}
break;
case CLEANING_MODE_OLD:
default:
foreach ($files as $val){
if (filemtime($this->getOption($value) . $val) < time()){
@unlink($this->getOption($value) . $val);
}
}
break;
}
}
}
}
/**
* 取臨時文件夾為緩存文件夾
* @return $dir 臨時文件夾路徑
*/
public function getTmpDir(){
$tmpdir = array();
foreach (array($_ENV, $_SERVER) as $tab) {
foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
if (isset($tab[$key])) {
if (($key == 'windir') or ($key == 'SystemRoot')) {
$dir = realpath($tab[$key] . '\\temp');
} else {
$dir = realpath($tab[$key]);
}
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
}
}
$upload = ini_get('upload_tmp_dir');
if ($upload) {
$dir = realpath($upload);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if (function_exists('sys_get_temp_dir')) {
$dir = sys_get_temp_dir();
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
//通過嘗試創建一個臨時文件來檢測
$tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
if ($tempFile) {
$dir = realpath(dirname($tempFile));
unlink($tempFile);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if ($this->_isGoodTmpDir('/tmp')) {
return '/tmp';
}
if ($this->_isGoodTmpDir('\\temp')) {
return '\\temp';
}
throw new Exception('無法確定臨時目錄,請手動指定cache_dir', E_USER_ERROR);
}
/**
* 驗證給定的臨時目錄是可讀和可寫的
*
* @param string $dir 臨時文件夾路徑
* @return boolean true or false 臨時文件夾路徑是否可讀寫
*/
protected function _isGoodTmpDir($dir){
if (is_readable($dir)) {
if (is_writable($dir)) {
return true;
}
}
return false;
}
}//endclass