设为首页 收藏本站
查看: 587|回复: 0

[经验分享] PHP比较全面的缓存类

[复制链接]

尚未签到

发表于 2017-4-5 07:09:49 | 显示全部楼层 |阅读模式
<?php
/*
* Name:    wrapperCache
* Notes:   wrapper cache for fileCache, memcache/memcached, APC, Xcache and eaccelerator
$cacheObj =wrapperCache::getInstance('memcache',30,array(array('host'=>'localhost')));
echo $cacheObj->cache('key','value');
*/
class wrapperCache {
const DEFAULT_MEMCACHE_PORT     = 11211;
const CACHE_TYPE_AUTO           = 'auto';
const CACHE_TYPE_EACCELERATOR   = 'eaccelerator';
const CACHE_TYPE_APC            = 'apc';
const CACHE_TYPE_MEMCACHE       = 'memcache';
const CACHE_TYPE_MEMCACHED      = 'memcached';
const CACHE_TYPE_FILE           = 'filecache';
const CACHE_TYPE_XCACHE         = 'xcache';
private $cache_params;   //extra params for external caches like path or connection option memcached
public  $cache_expire;   //seconds that the cache expires
private $cache_type;     //type of cache to use
private $cache_external; //external instance of cache, can be fileCache or memcache
private static $instance;//Instance of this class
// Always returns only one instance
public static function getInstance($type=self::CACHE_TYPE_AUTO, $exp_time=3600, $params='cache/'){
if (!isset(self::$instance)) { //doesn't exists the isntance
self::$instance = new self($type, $exp_time, $params); //goes to the constructor
}
return self::$instance;
}
//cache constructor, optional expiring time and cache path
private function __construct($type, $exp_time, $params) {
$this->cache_expire = $exp_time;
$this->cache_params = $params;
$this->setCacheType($type);
}
public function __destruct() {
unset($this->cache_external);
}
// Prevent users to clone the instance
public function __clone(){
$this->cacheError('Clone is not allowed.');
}
//deletes cache from folder
public function clearCache(){
switch($this->cache_type){
case self::CACHE_TYPE_EACCELERATOR :
eaccelerator_clean();
eaccelerator_clear();
break;
case self::CACHE_TYPE_APC :
apc_clear_cache('user');
break;
case self::CACHE_TYPE_XCACHE :
xcache_clear_cache(XC_TYPE_VAR, 0);
break;
case self::CACHE_TYPE_MEMCACHE :
$this->cache_external->flush();
break;
case self::CACHE_TYPE_MEMCACHED :
$this->cache_external->flush();
break;
case self::CACHE_TYPE_FILE:
$this->cache_external->deleteCache();
break;
}
}
//writes or reads the cache
public function cache($key, $value = '', $ttl = '') {
if ($value != '') { //wants to write
if ($ttl == '') $ttl = $this->cache_expire;
$this->put($key, $value, $ttl);
} else return $this->get($key);
//reading value
}
//creates new cache files with the given data, $key== name of the cache, data the info/values to store
private function put($key, $data, $ttl = '') {
if ($ttl == '') $ttl = $this->cache_expire;
switch($this->cache_type){
case self::CACHE_TYPE_EACCELERATOR :
eaccelerator_put($key, serialize($data), $ttl);
break;
case self::CACHE_TYPE_APC :
apc_store($key, $data, $ttl);
break;
case self::CACHE_TYPE_XCACHE :
xcache_set($key, serialize($data), $ttl);
break;
case self::CACHE_TYPE_MEMCACHE :
$data=serialize($data);
$this->cache_external->set($key, $data, false, $ttl);
break;
case self::CACHE_TYPE_MEMCACHED :
$data=serialize($data);
$this->cache_external->set($key, $data, $ttl);
break;
case self::CACHE_TYPE_FILE :
$this->cache_external->cache($key,$data);
break;
}
}
//returns cache for the given key
private function get($key){
switch($this->cache_type){
case self::CACHE_TYPE_EACCELERATOR :
$data =  unserialize(eaccelerator_get($key));
break;
case self::CACHE_TYPE_APC :
$data =  apc_fetch($key);
break;
case self::CACHE_TYPE_XCACHE :
$data =  unserialize(xcache_get($key));
break;
case self::CACHE_TYPE_MEMCACHE :
$data = unserialize($this->cache_external->get($key));
break;
case self::CACHE_TYPE_MEMCACHED :
$data = unserialize($this->cache_external->get($key));
break;
case self::CACHE_TYPE_FILE :
$data = $this->cache_external->cache($key);
break;
}
return $data;
}
//delete key from cache
public function delete($key){
switch($this->cache_type){
case self::CACHE_TYPE_EACCELERATOR :
eaccelerator_rm($key);
break;
case self::CACHE_TYPE_APC :
apc_delete($key);
break;
case self::CACHE_TYPE_XCACHE :
xcache_unset($key);
break;
case self::CACHE_TYPE_MEMCACHE :
$this->cache_external->delete($key);
break;
case self::CACHE_TYPE_MEMCACHED :
$this->cache_external->delete($key);
break;
case self::CACHE_TYPE_FILE :
$this->cache_external->delete($key);
break;
}
}
// Overloading for the Application variables and automatically cached
public function __set($name, $value) {
$this->put($name, $value, $this->cache_expire);
}
public function __get($name) {
return $this->get($name);
}
public function __isset($key) {//echo "Is '$name' set?\n"
if ($this->get($key) !== false)  return true;
else return false;
}
public function __unset($name) {//echo "Unsetting '$name'\n";
$this->delete($name);
}
//end overloads
public function getCacheType(){
return $this->cache_type;
}
//sets the cache if its installed if not triggers error
public function setCacheType($type){
$this->cache_type=strtolower($type);
switch($this->cache_type){
case self::CACHE_TYPE_EACCELERATOR :
if (!function_exists('eaccelerator_get')) $this->cacheError('eaccelerator not found');
break;
case self::CACHE_TYPE_APC :
if (!function_exists('apc_fetch')) $this->cacheError('APC not found');
break;
case self::CACHE_TYPE_XCACHE :
if (function_exists('xcache_get')) $this->cacheError('Xcache not found');
break;
case self::CACHE_TYPE_MEMCACHE :
if (class_exists('Memcache')) $this->init_mem();
else $this->cacheError('memcache not found');
break;
case self::CACHE_TYPE_MEMCACHED :
if (class_exists('Memcached')) $this->init_mem(true);
else $this->cacheError('memcached not found');
break;
case self::CACHE_TYPE_FILE :
if (class_exists('fileCache'))$this->init_filecache();
else $this->cacheError('fileCache not found');
break;
case self::CACHE_TYPE_AUTO ://try to auto select a cache system
if (function_exists('eaccelerator_get'))    $this->cache_type = self::CACHE_TYPE_EACCELERATOR;
elseif (function_exists('apc_fetch'))       $this->cache_type = self::CACHE_TYPE_APC ;
elseif (function_exists('xcache_get'))      $this->cache_type = self::CACHE_TYPE_XCACHE;
elseif (class_exists('Memcache'))           $this->init_mem();
elseif (class_exists('Memcached'))          $this->init_mem(true);
elseif (class_exists('fileCache'))          $this->init_filecache();
else $this->cacheError('not any compatible cache was found');
break;
default://not any cache selected or wrong one selected
$msg='Not any cache type selected';
if (isset($type)) $msg='Unrecognized cache type selected <b>'.$type.'</b>';
$this->cacheError($msg);
break;
}
}
private function init_mem($useMemecached = false) { //get instance of the memcache/memcached class
if (is_array($this->cache_params)) {
if ($useMemecached) {
$this->cache_type = self::CACHE_TYPE_MEMCACHED;
$this->cache_external = new Memcached();
} else {
$this->cache_type = self::CACHE_TYPE_MEMCACHE;
$this->cache_external = new Memcache;
}
foreach ($this->cache_params as $server) {
$server['port'] = isset($server['port']) ? (int)$server['port'] : self::DEFAULT_MEMCACHE_PORT;
if ($useMemecached) {
$this->cache_external->addServer($server['host'], $server['port']);
} else {
$server['persistent'] = isset($server['persistent']) ? (bool)$server['persistent'] : true;
$this->cache_external->addServer($server['host'], $server['port'], $server['persistent']);
}
}
} else $this->cacheError($this->cache_type . ' needs an array, example:wrapperCache::getInstance("' . $this->cache_type . '",30,array(array("host"=>"localhost")));');
}
private function init_filecache(){//get instance of the filecache class
$this->cache_type = self::CACHE_TYPE_FILE ;
$this->cache_external = fileCache::getInstance($this->cache_expire, $this->cache_params);
}
public function getAvailableCache($return_format='html'){//returns the available cache
$avCaches   = array();
$avCaches[] = array(self::CACHE_TYPE_EACCELERATOR,function_exists('eaccelerator_get'));
$avCaches[] = array(self::CACHE_TYPE_APC,         function_exists('apc_fetch')) ;
$avCaches[] = array(self::CACHE_TYPE_XCACHE,      function_exists('xcache_get'));
$avCaches[] = array(self::CACHE_TYPE_MEMCACHE,    class_exists('Memcache'));
$avCaches[] = array(self::CACHE_TYPE_MEMCACHED,   class_exists('Memcached'));
$avCaches[] = array(self::CACHE_TYPE_FILE,        class_exists('fileCache'));
if ($return_format == 'html') {
$ret = '<ul>';
foreach ($avCaches as $c) {
$ret .= '<li>' . $c[0] . ' - ';
if ($c[1]) $ret .= 'Found/Compatible';
else $ret .= 'Not Found/Incompatible';
$ret .= '</ll>';
}
return $ret . '</ul>';
} else return $avCaches;
}
private function cacheError($msg){//triggers error
trigger_error('<br /><b>wrapperCache error</b>: '.$msg.
'<br />If you want you can try with \'auto\' for auto select a compatible cache.
<br />Or choose a supported cache from list:'.$this->getAvailableCache(), E_USER_ERROR);
}
}
 wrapperCache基于文件的缓存处理类
<?php
/*
* Name:    fileCache
fileCache::getInstance(3600,'E:\www\cache\\')->cache('key','value');
* Notes:   fileCache class, caches variables in standalone files if value is too long or uses unique file for small ones
*/
class fileCache {
private $cache_path;//path for the cache
private $cache_expire;//seconds that the cache expires
private $application=array();//application object like in ASP
private $application_file;//file for the application object
private $application_write=false;//if application write is true means there was changes and we need to write the app file
private $debug=false; //no debug by default
private $log=array();//log for the debug system
private $start_time=0;//application start time
private static $content_size=64;//this is the max size can be used in APP cache if bigger writes independent file
private static $instance;//Instance of this class
// Always returns only one instance
public static function getInstance($exp_time=3600,$path='cache/'){
if (!isset(self::$instance)){//doesn't exists the isntance
self::$instance = new self($exp_time,$path);//goes to the constructor
}
return self::$instance;
}
//cache constructor, optional expiring time and cache path
private function __construct($exp_time,$path){
$this->start_time=microtime(true);//time starts
$this->cache_expire=$exp_time;
if ( ! is_writable($path) ) trigger_error('Path not writable:'.$path);
else $this->cache_path=$path;
$this->APP_start();//starting application cache
}
public function __destruct() {
$this->addLog('destruct');
$this->APP_write();//on destruct we write if needed
$this->returnDebug();
}
// Prevent users to clone the instance
public function __clone(){
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
//deletes cache from folder
public function deleteCache($older_than=''){
$this->addLog('delete cache');
if (!is_numeric($older_than)) $older_than=0;
$files = scandir($this->cache_path);
foreach($files as $file){
if (strlen($file)>2 && time() > (filemtime($this->cache_path.$file) + $older_than) ) {
unlink($this->cache_path.$file);//echo "<br />-".$file;
$this->addLog('delete cache file:'.$this->cache_path.$file);
}
}
}
//writes or reads the cache
public function cache($key, $value=''){
if ($value!=''){//wants to write
if (strlen(serialize($value)) > 64 ){//write independent file it's a big result
$this->addLog('cache function write in file key:'. $key);
$this->put($key, $value);
}else{
$this->addLog('cache function write in APP key:'. $key);
$this->APP($key,$value);//write in the APP cache
}
}else{//reading value
if ( $this->APP($key)!=null ){
$this->addLog('cache function read APP key:'. $key);
return $this->APP($key);//returns from app cache
}else{
$this->addLog('cache function read file key:'. $key);
return $this->get($key);//returns from file cache
}
}
}
//deletes a key from cache
public function delete($name){
if ( $this->APP($name)!=null ){//unset the APP var
$this->addLog('unset APP key:'. $name);
unset($this->application[md5($name)]);
$this->application_write=true;//says that we have changes to later save the APP
}elseif ( file_exists($this->fileName($name)) ){//unlink filename
$this->addLog('unset File key:'. $name);
unlink($this->fileName($name));
}
}
// Overloading for the variables and automatically cached
public function __set($name, $value) {
$this->cache($name, $value);
}
public function __get($name) {
return $this->cache($name);
}
public function __isset($name) {//echo "Is '$name' set?\n"
$this->addLog('isset key:'. $name);
$value=$this->cache($name);
return isset($value);
}
public function __unset($name) {//echo "Unsetting '$name'\n";
$this->delete($name);
}
//end overloads
//////////Cache for files individually///////////////////
//creates new cache files with the given data, $key== name of the cache, data the info/values to store
private function put($key, $data){
if ( $this->get($key)!= $data ){//only write if it's different
$values = serialize($data);
$filename = $this->fileName($key);
$file = fopen($filename, 'w');
if ($file){//able to create the file
$this->addLog('writting key: '.$key.' file: '.$filename);
fwrite($file, $values);
fclose($file);
}
else  $this->addLog('unable to write key: '.$key.' file: '.$filename);
}//end if different
}
//returns cache for the given key
private function get($key){
$filename = $this->fileName($key);
if (!file_exists($filename) || !is_readable($filename)){//can't read the cache
$this->addLog('can\'t read key: '.$key.' file: '.$filename);
return null;
}
if ( time() < (filemtime($filename) + $this->cache_expire) ) {//cache for the key not expired
$file = fopen($filename, 'r');// read data file
if ($file){//able to open the file
$data = fread($file, filesize($filename));
fclose($file);
$this->addLog('reading key: '.$key.' file: '.$filename);
return unserialize($data);//return the values
}else{
$this->addLog('unable to read key: '.$key.' file: '.$filename);
return null;
}
}else{
$this->addLog('expired key: '.$key.' file: '.$filename);
unlink($filename);
return null;//was expired you need to create new
}
}
//returns the filename for the cache
private function fileName($key){
return $this->cache_path.md5($key);
}
//////////END Cache for files individually///////////////////
//////////Cache for APP variables///////////////////
//load variables from the file
private function APP_start ($app_file='application'){
$this->application_file=$app_file;
if (file_exists($this->cache_path.$this->application_file)){ // if data file exists, load the cached variables
//erase the cache every X minutes
$app_time=filemtime($this->cache_path.$this->application_file)+$this->cache_expire;
if (time()>$app_time){
$this->addLog('deleting APP file: '.$this->cache_path.$this->application_file);
unlink ($this->cache_path.$this->application_file);//erase the cache
}else{//not expired
$filesize=filesize($this->cache_path.$this->application_file);
if ($filesize>0){
$file = fopen($this->cache_path.$this->application_file, 'r');// read data file
if ($file){
$this->addLog('reading APP file: '.$this->cache_path.$this->application_file);
$data = fread($file, $filesize);
fclose($file);
$this->application = unserialize($data);// build application variables from data file
}//en if file could open
}//end if file size
}
}else{//if the file does not exist we create it
$this->addLog('creating APP file: '.$this->cache_path.$this->application_file);
fopen($this->cache_path.$this->application_file, 'w');
}
}
// write application data to file
private function APP_write(){
if ($this->application_write){
$data = serialize($this->application);
$file = fopen($this->cache_path.$this->application_file, 'w');
if ($file){
$this->addLog('writting APP file: '.$this->cache_path.$this->application_file);
fwrite($file, $data);
fclose($file);
}
}
}
//returns the value form APP cache or stores it
private function APP($var,$value=''){
if ($value!=''){//wants to write
if (is_array($this->application)){
if ( array_key_exists(md5($var), $this->application) ){//exist the value in the APP
$write=false;//we don't need to wirte
if ($this->application[md5($var)]!=$value)$write=true;//but exists and is different then we write
}
else $write=true;//not set we write!
}
else $write=false;
if ($write){
$this->addLog('writting APP key:'.$var);
$this->application[md5($var)]=$value;
$this->application_write=true;//says that we have changes to later save the APP
}
}else{//reading
if ( !is_array($this->application) || ! array_key_exists(md5($var), $this->application) ){
$this->addLog('nothing found for APP key:'.$var);
return null;//nothing found not in array
}else{
$this->addLog('reading APP key:'.$var);
return $this->application[md5($var)];//return value
}
}
}
//////////End Cache for APP variables///////////////////
////DEBUG
//sets debug on or off
public function setDebug($state){
$this->debug=(bool) $state;
}
public function returnDebug($type='HTML'){
if ($this->debug){
switch($type){
case 'array':
return $this->log;
break;
case 'HTML'://returns debug as HTML
echo '<ol>';
foreach($this->log as $key=>$value){//loop in the log var
echo '<li>'.$value.'</li>';
}
echo '</ol>';
break;
}
}
else return false;
}
//add debug log
public function addLog($value){
if ($this->debug){//only if debug enabled
array_push($this->log, round((microtime(true) - $this->start_time),5).'s - '. $value);
}
}
}
?>

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-360259-1-1.html 上篇帖子: PHP中正则表达式详细说明 下篇帖子: DX 2.0 class_credits.php解析
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表