一个简单的页面缓存类

    最近学习的过程中接触到了PHP的缓存 ,一开始什么APC、Memcache、eAccelerator、xcache、mmcache、zend cache、pear cache还有各种网上的缓存类等等把我都搞糊涂了,经过慢慢整理才有了一个粗浅的认识。
    上面列举的那些缓存是不尽相同的,有些是比较底层的编译型缓存,对于这些缓存,更确切的说是给PHP加速,例如APC;有些是页面层次的缓存,缓存一些页面所需的数据或是页面的某个部分(某个函数、某个代码片段之类)或是整个页面,具体的可以缓存到文件、内存或是数据库,例如pear_cache。
    或许还有一些其它类型的缓存,但是我目前还没接触到,而且对于上面列举的那些缓存具体是什么类型的缓存,我目前也没有具体的认识,以后还要花功夫学习。
    看了网上的一些页面缓存类,自己也写了一个(下面会贴出来),功能很简单,就是缓存整个页面,以后有需要再做扩展。
    这里说一下这个缓存类的安全问题,其实网上其它的类似缓存类都有同样的问题,包括smarty的缓存,这个在smarty的手册里有说明(具体在缓存章节的每页多个缓存小节),问题的根源在于cacheid的设定,cacheid一般是根据url的文件名和post或get的参数来生成,这样的话,如果某个不怀好意的人写一些代码来连续快速发送post或get参数,就会让服务器一直生成缓存文件,消耗服务器资源,具体的理解结合以下代码会更容易。暂时好像还没有好的解决方案,一个不太好的方法是在页面里要自己添加代码检查用于设定cacheid的post或get参数值的合法性。

 

<? php
/* *
 * 可自由转载,请保留版权信息,谢谢使用!
 * Class Name : Junin_Cache (For PHP5)
 * Version : 1.0
 * Description : 动态缓存类,用于控制页面自动生成缓存、调用缓存、更新缓存、删除缓存.
 * Author : junin927@hotmail.com,Junin
 * Author Page : http://sdts.blog.hexun.com/ http://blog.csdn.net/sdts/
 * Last Modify : 2007-8-23
 * Remark : 
   1.此版本为PHP5版本,本人暂没有写PHP4的版本,如需要请自行参考修改.
   2.此版本为utf-8编码,如果网站采用其它编码请自行转换,Windows系统用记事本打开另存为,选择相应编码即可(一般ANSI),linux下请使用相应编辑软件或iconv命令行.
   3.拷贝粘贴的就不用管上面第2条了.
   4.请在实例化对象后调用SetCacheId()函数,此调用要先于其它缓存操作.
 * 关于缓存的一点感想:
 * 动态缓存和静态缓存的根本差别在于其是自动的,用户访问页面过程就是生成缓存、浏览缓存、更新缓存的过程,无需人工操作干预.
 * 静态缓存指的就是生成静态页面,相关操作一般是在网站后台完成,需人工操作(也就是手动生成).
 
*/
/* *
 * 使用方法举例
 * Demo1
   <?php
    header('content-type:text/html;charset=utf-8');
    require_once('Junin_Cache.php');
    $cachedir = './Cache/'; //设定缓存目录
    $cache = new Junin_Cache($cachedir,10); //省略参数即采用缺省设置, $cache = new Cache($cachedir);
    $cache->SetCacheId(); //根据get或post的参数设置cache
    if ($_GET['cacheact'] != 'rewrite') //此处为一技巧,通过xx.php?cacheact=rewrite更新缓存,以此类推,还可以设定一些其它操作
        $cache->Load(); //装载缓存,缓存有效则不执行以下页面代码
    //页面代码开始
    echo date('H:i:s jS F');
    //页面代码结束
    $cache->Write(); //首次运行或缓存过期,生成缓存
   ?>
  *Demo2
    <?php
    header('content-type:text/html;charset=utf-8');
    require_once('Junin_Cache.php');
    $cachedir = './Cache/'; //设定缓存目录
    $cache = new Junin_Cache($cachedir,10); //省略参数即采用缺省设置, $cache = new Cache($cachedir);
    $cache->SetCacheId('classid','articleid'); //根据get或post的参数设置cache,针对类似这样的url:http://xxx/article.php?classid=1&articleid=1001
    if ($_GET['cacheact'] != 'rewrite') //此处为一技巧,通过xx.php?cacheact=rewrite更新缓存,以此类推,还可以设定一些其它操作
        $cache->Load(); //装载缓存,缓存有效则不执行以下页面代码
    //页面代码开始
    $content = date('H:i:s jS F');
    echo $content;
    //页面代码结束
    $cache->Write(1,$content); //首次运行或缓存过期,生成缓存
    ?>
   *Demo3
    <?php
    header('content-type:text/html;charset=utf-8');
    require_once('Junin_Cache.php');
    define('CACHEENABLE',true);
    if (CACHEENABLE) {
        $cachedir = './Cache/'; //设定缓存目录
        $cache = new Junin_Cache($cachedir,10); //省略参数即采用缺省设置, $cache = new Cache($cachedir);
        $cache->SetCacheId(); //根据get或post的参数设置cache
        if ($_GET['cacheact'] != 'rewrite') //此处为一技巧,通过xx.php?cacheact=rewrite更新缓存,以此类推,还可以设定一些其它操作
            $cache->Load(); //装载缓存,缓存有效则不执行以下页面代码    
    }
    //页面代码开始
    $content = date('H:i:s jS F');
    echo $content;
    //页面代码结束
    if (CACHEENABLE)
        $cache->Write(1,$content); //首次运行或缓存过期,生成缓存
    ?>
 
*/
class  Junin_Cache {
    
/* *
     * 注意 : 请在实例化对象后调用SetCacheId()函数,此调用要先于其它缓存操作.
     * 
     * $mDir : 缓存文件存放目录
     * $mLifeTime : 缓存文件有效期,单位为秒
     * $mCacheId : 缓存文件路径,包含文件名
     * $mExt : 缓存文件扩展名(可以不用),这里使用是为了查看文件方便
     
*/
    
private   $mDir ;
    
private   $mLifeTime ;
    
private   $mCacheId ;
    
private   $mExt ;
    
/* *
     * 析构函数,检查缓存目录是否有效,默认赋值
     
*/
    
function  __construct( $pDir = '' , $pLifeTime = 1800 ) {
        
if  ( $this -> CheckDir( $pDir )) {
            
$this -> mDir  =   $pDir ;
            
$this -> mLifeTime  =   $pLifeTime ;
            
$this -> mExt  =   ' .php ' ;
            
$this -> mCacheId  =   '' ;
        }
    }
    
/* *
     * 设定CacheId
     * 把页面文件名和查询参数值组合(这样的组合在整个Web应用程序中唯一)加密生成唯一标识作为缓存文件名
     * 必须在所有缓存操作前调用
     
*/
    
public   function  SetCacheId() {
        
$param   =   func_get_args ();
        
$str   =   $_SERVER [ ' PHP_SELF ' ];
        
if  ( is_array ( $param ) &&! empty ( $param )) {
            
foreach  ( $param   as   $value ) {
                
$str   .=   $_REQUEST [ $value ];
            }            
        }
        
$this -> mCacheId  =   $this -> mDir . md5 ( $str ) . $this -> mExt;
    }
    
/* *
     * 检查缓存是否有效,此处无需调用CheckCacheId()检查,因为该操作的调用在CheckCacheId()之后,并且如果mCacheId未设置,同样会返回false
     
*/
    
private   function  IsValid() {
        
if  ( ! file_exists ( $this -> mCacheId))  return   false ;
        
if  ( ! (@ $mtime   =   filemtime ( $this -> mCacheId)))  return   false ;
        
if  ( mktime ()  -   $mtime   >   $this -> mLifeTime)  return   false ;
        
return   true ;
    }
    
/* *
     * 写入缓存
     * $mode == 0 , 以浏览器缓存的方式取得页面内容
     * $mode == 1 , 以直接赋值(通过$content参数接收)的方式取得页面内容
     * $mode == 2 , 以本地读取(fopen ile_get_contents)的方式取得页面内容(似乎这种方式没什么必要)
     
*/
    
public   function  Write( $pMode = 0 , $pContent = '' ) {
        
if  ( ! $this -> CheckCacheId())
            
$this -> HandleError( ' mCacheId属性未设置,请在操作缓存前调用SetCacheId()设置该属性. ' );
        
switch  ( $pMode ) {
            
case   0 :
                
$pContent   =   ob_get_contents ();
                
break ;
            
default :
                
break ;
        }
        
ob_end_flush ();
        
if  ( is_writeable ( $this -> mCacheId))
            
file_put_contents ( $this -> mCacheId , $pContent );
        
else  
            
$this -> HandleError( ' 写入缓存失败!请检查目录权限! ' );
    }
    
/* *
     * 加载缓存
     * exit() 载入缓存后终止原页面程序的执行,缓存无效则运行原页面程序生成缓存
     * ob_start() 开启浏览器缓存用于在页面结尾处取得页面内容
     
*/
    
public   function  Load() {
        
if  ( ! $this -> CheckCacheId())
            
$this -> HandleError( ' mCacheId属性未设置,请在加载和生成缓存前调用SetCacheId()设置该属性. ' );
        
if  ( $this -> IsValid()) {
            
echo   " <span style="display:none;">This is Cache.</span> " ;
            
// 以下两种方式,哪种方式好?????
             require_once ( $this -> mCacheId);
            
// echo file_get_contents($this->mCacheId);
             exit (); 
        }
        
else  {
            
ob_start ();
        }
    }
    
/* *
     * 清除缓存
     
*/
    
public   function  Clean() {
        
if  ( ! $this -> CheckCacheId())
            
$this -> HandleError( ' mCacheId属性未设置,请在加载和生成缓存前调用SetCacheId()设置该属性. ' );
        
if  (@ unlink ( $this -> mCacheId))
            
$this -> HandleError( ' 清除缓存文件失败!请检查目录权限! ' );
    }
    
/* *
     * 检查$mCacheId属性是否已设置,即检查SetCacheId()函数是否执行,SetCacheId后每个缓存操作都需要调用此函数检查mCacheId属性是否已赋值
     
*/
    
private   function  CheckCacheId() {
        
if  ( ''   ==   $this -> mCacheId)  return   false ;
        
return   true ;
    }
    
/* *
     * 检查目录是否存在或是否可创建
     
*/
    
private   function  CheckDir( $pDir ) {
        
if  ( is_dir ( $pDir ))  return   true ;
        
if  (@ mkdir ( $pDir , 0777 )) {
              
$this -> HandleError( ' 所设定缓存目录不存在并且创建失败!请检查目录权限! ' );
              
return   false ;
        }
        
return   true ;
    }
    
/* *
     * 输出错误信息
     
*/
    
private   function  HandleError( $pStr ) {
        
echo   ' <div style="color:red;"> ' . $pStr . ' </div> ' ;
        
exit ();
    }
}
?>

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值