/*
* 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 '.$type.'';
$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 = '
foreach ($avCaches as $c) {
$ret .= '
if ($c[1]) $ret .= 'Found/Compatible';
else $ret .= 'Not Found/Incompatible';
$ret .= '';
}
return $ret . '
} else return $avCaches;
}
private function cacheError($msg){//triggers error
trigger_error('
wrapperCache error: '.$msg.
'
If you want you can try with \'auto\' for auto select a compatible cache.
Or choose a supported cache from list:'.$this->getAvailableCache(), E_USER_ERROR);
}
}