Zend_Cache学习笔记

1.组成与初始化

Zend_Cache由两部分组成:前端操作与后端适配器。

前端操作就是针对具体实现所进行的一些动作,比如数据缓存、页面缓存等等。

后端适配器则决定你使用何种缓存工具,比如是MMC,还是Sqlite等等。

Zend_Cache的创建是由一个工厂方法Zend_Cache::factory()来实现的,该方法包含了四个参数,分别对应前后端的名称与配置,如:

$cache = Zend_Cache::factory(

'Core',

 'File',

 $frontendOptions, 

 $backendOptions

);


2.存储数据

Zend_Cache提供了save()方法来进行数据的存储,该方法包含五个参数:

$data :需要存储的数据

$id :数据的键名

$tags :标记,标记是给缓存纪录分类的一种方法.当保存一个缓存时,你可以给该缓存纪录设置一个或多个标记,多个标记以数组形式组织在一起 此后你不再需要该缓存纪录使,你可以清除所有指定标记的缓存纪录,对于一个项目中存在多种类型的缓存时,利用标记功能,可以达到批量处理缓存的效果。

$specificLifetime :缓存时间

$priority :优先级,范围为0-10

注意:Zend_Cache在存储之前,会自动对存储内容进行一个序列化操作(serailize()),因此用户无需手动序列化数据;同理,在获取数据时,也会自动进行反序列化操作(unserialize())。


3.获取数据

Zend_Cache提供了load()方法来进行数据的存储,该方法包含三个参数:

$id :缓存的键名

$doNotTestCacheValidity:不检查缓存的有效性,默认为false

$doNotUnserialize :不反序列化,默认为false


4.删除数据

(1)删除单个缓存

Zend_Cache提供了remove()方法来进行单个数据的删除,参数为数据的键名。

(2)删除多个缓存

当需要一次性删除多个缓存时,可以使用clean()方法,该方法包含两个参数:

$mode :模式,共四种:CLEANING_MODE_ALL,CLEANING_MODE_OLD,CLEANING_MODE_MATCHING_TAGCLEANING_MODE_NOT_MATCHING_TAG

$tags:   标记,用于批量删除同一类型的缓存


5.页面缓存的配置
Zend_Cache的页面缓存使用起来相当方便,利用的是Zend_Cache_Frontend_Page这个类来进行处理。大部分操作,这个类都已经实现了,我们要做的,仅仅是初始化缓存工具(比如Memcache),设置缓存信息,比如哪些页面需要缓存、缓存生效时间等。
配置文件的内容大致如下:
resources.cachemanager.memcache.frontend.options.cregexps.0.exp      = "/cfxf/index/index/"
resources.cachemanager.memcache.frontend.options.cregexps.0.cache       = true
resources.cachemanager.memcache.frontend.options.cregexps.0.lifetime = 180

resources.cachemanager.memcache.frontend.options.cregexps.1.exp       = "/cfxf/today/index/"
resources.cachemanager.memcache.frontend.options.cregexps.1.cache       = true
resources.cachemanager.memcache.frontend.options.cregexps.1.lifetime   = 180

一般我们选择在请求分发之前进行这一步操作,因此你可以将其编写为一个插件。
我是将缓存的信息写入了配置文件,然后在这个插件中,读取配置文件,初始化Memcache:
/**
 * 页面缓存控制器
 *
 * @author xxx@myhexin.com
 * @create 2012-06-14
 */

class Free_Controller_Plugin_PageCacheManager extends Zend_Controller_Plugin_Abstract
{
    /**
     * 用于分发前截获请求,查询缓存,若有则直接输出
     *
     * @param   Zend_Controller_Request_Abstract $request   请求对象
     * @return  null
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
     $configObj = Zend_Registry::get( 'application')-> application-> cache-> memcache;
     
      if (!$configObj-> open) {
           return;
     }    
     
     $frontOptions = $configObj->frontend ->options ->toArray();

     $backOptions = $configObj->backend ->options ->toArray();
     
     $regexps = array();

           if ( isset($configObj-> frontend-> cregexps)) {
              $regexps = $configObj->frontend ->cregexps ->toArray();
          }
          
          $newRegexps = array();
           foreach ($regexps as $item) {
              $newRegexps[$item[ 'exp']] = array();
              $tmpArr = array();
               foreach ($item as $key => $value) {
                    if ($key == 'exp') {
                         continue;
                   }
                   $tmpArr[$key] = $value;
              }
              $newRegexps[$item[ 'exp']] = $tmpArr;
          }
          $frontOptions[ 'regexps'] = $newRegexps;
     
           $memcache = Zend_Cache:: factory(
              $configObj-> frontend-> name, $configObj->backend ->name ,
              $frontOptions, $backOptions
          );
          
           if ($configObj-> clearcache) {
                $memcache->clean(Zend_Cache:: CLEANING_MODE_ALL );
          }
       
        $memcache ->start();
    }
}


上面生成的$memcache其实是类Zend_Cache_Frontend_Page的实例,我们可以跟进这个类的start方法,查看其是如何实现的:
    /**
     * Start the cache
     *
     * @param  string  $id       (optional) A cache id (if you set a value here,            maybe you have to use Output frontend instead)
     * @param  boolean $doNotDie For unit testing only !
     * @return boolean True if the cache is hit (false else)
     */
    public function start($id = false, $doNotDie = false)
    {
        $this-> _cancel = false;
        $lastMatchingRegexp = null;
        foreach ($this-> _specificOptions[ 'regexps'] as $regexp => $conf) {
           // 关键在这一句,通过当前请求的URI,和配置中的URL进行匹配,然后根据配置参数确定是否缓存
            if ( preg_match( "`$regexp `", $_SERVER['REQUEST_URI' ])) {
                $lastMatchingRegexp = $regexp;
            }
        }
        $this-> _activeOptions = $this->_specificOptions ['default_options' ];
       
        if ($lastMatchingRegexp !== null) {
            $conf = $this->_specificOptions ['regexps' ][$lastMatchingRegexp];
         
            foreach ($conf as $key=>$value) {
                $this-> _activeOptions[$key] = $value;
            }
        }
        if (!($this-> _activeOptions[ 'cache'])) {
            return false;
        }
        if (!$id) {
            $id = $this->_makeId();
            if (!$id) {
                return false;
            }
        }
        // 后面这部分就是常规的缓存实现了  
        $array = $this->load($id);
        if ($array !== false) {
            $data = $array[ 'data'];
            $headers = $array[ 'headers'];
            if (! headers_sent()) {
                foreach ($headers as $key=>$headerCouple) {
                    $name = $headerCouple[0];
                    $value = $headerCouple[1];
                    header( "$name : $value ");
                }
            }
            if ($this-> _specificOptions[ 'debug_header']) {
                echo 'DEBUG HEADER : This is a cached page !';
            }
            echo $data;
            if ($doNotDie) {
                return true;
            }
            die();
        }
        ob_start( array($this, '_flush'));
        ob_implicit_flush( false);
        return false;
    }


有没有发现什么问题呢?仔细看这一句:
preg_match( "`$regexp `", $_SERVER['REQUEST_URI' ])
我们平时在浏览器地址栏填写url的时候,因为可能服务端做了一些处理,你无须输入完整的url也能正常访问页面,就比如http://www.10jqka.com.cn/module/index/index/http://www.10jqka.com.cn/module/其实是一样的效果(Zend框架如果不写,默认访问index控制器和action),但是在设置页面缓存的时候,千万不能这样省略,因为如果省略的话,preg_match函数可能会匹配到多项,而这段代码只会选择最后一项作为结果。
举个例子,如果你的配置是这样的:
resources.cachemanager.memcache.frontend.options.cregexps.0.exp      = "/cfxf/today/index/"
resources.cachemanager.memcache.frontend.options.cregexps.0.cache       = true
resources.cachemanager.memcache.frontend.options.cregexps.0.lifetime = 180

resources.cachemanager.memcache.frontend.options.cregexps.1.exp       = "/cfxf/"
resources.cachemanager.memcache.frontend.options.cregexps.1.cache       = true
resources.cachemanager.memcache.frontend.options.cregexps.1.lifetime   = 180
而你当前访问的地址是/cfxf/today/index/,那么你会发现,上述代码匹配后的结果是/cfxf/而非/cfxf/today/index/。因此,我们写配置的时候,一定要格式统一,尽量写成/module/controller/action/的形式。当然,你也可以选择写成正则表达式。

接下来,你就可以开启配置中的debug_header,测试缓存效果了。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值