<?php
define('APPPATH',dirname(__FILE__));
$config=array();
$config['cache']=array(
'memcache' =>array(
'servers'=>array(
'memcache1'=>array('host'=>'127.0.0.1','port'=>11211,'weight'=>25),
),
'ttl'=>60*24, //一个小时,0代表永不过期
),
'file' =>array(
//'mode' =>1, //1 按key存文件,2 按天存文件,3按小时存文件
'path' =>APPPATH.'/cache',
'ext' =>'.cache',
'ttl'=>60*24, //一个小时,0代表永不过期
),
);
interface Cache{
public function get($key);
public function set($key,$val,$ttl);
public function delete($key,$ttl=0);
public function clean();
}
class Cache_memcache implements Cache{
private $default_config=array('host'=>'127.0.0.1','port'=>11211,'weight'=>1);
private static $memcache;
private $ttl=0;
function __construct($config=array()){
if (!isset(self::$memcache)) {
self::$memcache = new Memcache;
}
if (isset($config['ttl'])) {
$this->ttl=$config['ttl'];
}
//如果由配置信息,则根据配置信息初始化,否则加载默认配置
if (isset($config['servers']) && is_array($config['servers'])) {
foreach ($config['servers'] as $server) {
self::$memcache->addServer($server['host'],$server['port'],TRUE,$server['weight']);
}
}else{
self::$memcache->addServer($this->default_config['host'],$this->default_config['port'],TRUE,$this->default_config['weight']);
}
}
public function get($key){
if (isset(self::$memcache)) {
return self::$memcache->get($key);
}else{
return FALSE;
}
}
public function set($key,$val,$ttl=-1){
if (isset(self::$memcache)) {
if ($ttl<0) {
$ttl=$this->ttl;
}
return self::$memcache->set($key, $val, 0, $ttl);
}else{
return FALSE;
}
}
public function delete($key,$ttl=0){
if (isset(self::$memcache)) {
return self::$memcache->delete($key,$ttl);
}else{
return FALSE;
}
}
public function clean(){
if (isset(self::$memcache)) {
return self::$memcache->flush();
}else{
return FALSE;
}
}
}
class Cache_file implements Cache{
private static $path;
private $def_path='./cache';
private $ttl=0;
private $ext='.cache';
function __construct($config=array()){
if (isset($config['ttl'])) {
$this->ttl=$config['ttl'];
}
if(isset($config['path'])) {
$path=rtrim($config['path'],DIRECTORY_SEPARATOR);
$this->def_path=self::$path=$path;
}else{
self::$path=$this->def_path;
}
if(!file_exists(self::$path)){
$this->_mkdirs(self::$path);
}
}
//在主缓存路径下设置缓存文件夹
// "./",".",""都表示初始缓存目录
public function setPath($dirname){
$dirname=trim($dirname,DIRECTORY_SEPARATOR);
$path=$this->def_path.'/'.$dirname;
try {
if (!file_exists($path)) {
$this->_mkdirs($path);
}
self::$path=$path;
return TRUE;
} catch (Exception $e) {
return FALSE;
}
}
public function _mkdirs($path, $mode = 0777)
{
if (is_dir($path) || @mkdir($path, $mode)) return TRUE;
if (!$this->_mkdirs(dirname($path), $mode)) return FALSE;
return @mkdir($path, $mode);
}
public function _cleanDir($path,$rmdir=FALSE){
if (!$dir = @opendir($path)){
return FALSE;
}
while (FALSE!==($item=readdir($dir))) {
if (in_array($item, array('.','..'))) {
continue;
}
$f=$path.DIRECTORY_SEPARATOR.$item;
if (is_dir($f)) {
$this->_cleanDir($f,TRUE);
}else{
unlink($f);
}
}
closedir($dir);
if ($rmdir) {
return rmdir($path);
}
}
public function get($key){
$fname=$this->_get_fname($key);
if (file_exists($fname)) {
$data=file_get_contents($fname);
$data=unserialize($data);
//判断过期
if (is_array($data)) {
if ($data['ttl']==0 || time()-$data['stime']<$data['ttl']) {
return $data['data'];
}
}
@unlink($this->_get_fname($key));
}
return FALSE;
}
public function set($key,$val,$ttl=-1){
if ($ttl<0) {
$ttl=$this->ttl;
}
$path=$this->_get_fname($key);
if (!@$fp = fopen($path,'w+'))
{
return FALSE;
}
//组合数据
$data=array(
'ttl'=>$ttl,
'stime'=>time(),
'data'=>$val,
);
$data=serialize($data);
try {
flock($fp, LOCK_EX);
fwrite($fp, $data);
flock($fp, LOCK_UN);
fclose($fp);
//file_put_contents($path, $data,LOCK_EX);
@chmod($path, 0777);
return TRUE;
} catch (Exception $e) {
return FALSE;
}
}
public function delete($key,$ttl=0){
return unlink($this->_get_fname($key));
}
public function clean(){
return $this->_cleanDir($this->def_path);
}
private function _get_fname($key){
return self::$path.'/'.$key.$this->ext;
}
}
class Drive{
public $config;
protected $drive_type; //驱动类型 lower
protected $lib_class;
protected static $driver_list=array('cache'); //支持的驱动接口列表
function __construct($config=array()){
$this->config=$config;
}
//链式获取驱动实例
function __get($child){
//第一层驱动接口
if (in_array($child, self::$driver_list)) {
$lib_name=ucfirst($child);
if(interface_exists($lib_name)){
$this->drive_type=$child;
return $this;
}
return FALSE;
}else{
//第二层判断实例是否存在,否则创建
$drive_class=ucfirst($this->drive_type);
$lib_name=$drive_class.'_'.$child;
$this->lib_class=$child;
if (isset(self::$driver_list[$this->drive_type][$child])) {
return $this;
}else{
if(class_exists($lib_name) && in_array($drive_class, class_implements($lib_name)) ) {
$refClass= new ReflectionClass($lib_name);
$instance=$refClass->newInstance($this->config[$this->drive_type]);
self::$driver_list[$this->drive_type][$child]=array(
'refClass'=>$refClass,
'instance'=>$instance,
);
return $this;
}
}
return FALSE;
}
}
function __call($method,$args=array()){
if (isset($this->drive_type)) {
$drivesc=self::$driver_list[$this->drive_type];
if(isset($drivesc[$this->lib_class]) && $drivesc[$this->lib_class]['refClass']->hasMethod($method)){
return call_user_func_array(array($drivesc[$this->lib_class]['instance'],$method), $args);
}
}
return FALSE;
}
}
//运行实例
//driver->驱动接口->驱动类->方法
$drive=new Drive($config);
$drive->cache->memcache->set('ok','1000',1);
$val=$drive->cache->memcache->get("ok1");
////////////
$drive->cache->file->set('ok',array('a'=>100));
$drive->cache->file->setPath('a/b');
$drive->cache->file->set('ok',array('a'=>111));
$val=$drive->cache->file->get('ok');
var_dump($val);
$drive->cache->file->setPath('.');
$val=$drive->cache->file->get('ok');
var_dump($val);
//$drive->cache->file->clean();
////////////////