首页 > PHP开发 > Yii1 > Yii的缓存使用详细教程
2014
11-11

Yii的缓存使用详细教程

├──CApcCache.php

├──CCache.php

├──CDbCache.php

├──CDummyCache.php

├──CEAcceleratorCache.php

├──CFileCache.php

├──CMemCache.php

├──CWinCache.php

├──CXCache.php

├──CZendDataCache.php

└──dependencies

├──CCacheDependency.php

├──CChainedCacheDependency.php

├──CDbCacheDependency.php

├──CDirectoryCacheDependency.php

├──CExpressionDependency.php

├──CFileCacheDependency.php

└──CGlobalStateCacheDependency.php

1 directory, 17 files

Yii提供了不同的缓存组件,可以将缓存数据存储到不同的媒介中。例如,CMemCache组件封装了PHP的memcache扩展并使用内存作为缓存存储媒介。CApcCache组件封装了PHP APC扩展;而CDbCache组件会将缓存的数据存入数据库。下面是一个可用缓存组件的列表:

·CMemCache:使用PHP memcache扩展.

·CApcCache:使用PHP APC扩展.

·CXCache:使用PHP XCache扩展。注意,这个是从1.0.1版本开始支持的。

·CEAcceleratorCache:使用PHP EAccelerator扩展.

·CDbCache:使用一个数据表存储缓存数据。默认情况下,它将创建并使用在runtime目录下的一个SQLite3数据库。你也可以通过设置其connectionID属性指定一个给它使用的数据库。

·CZendDataCache:使用Zend Data Cache作为后台缓存媒介。注意,这个是从1.0.4版本开始支持的。

·CFileCache:使用文件存储缓存数据。这个特别适合用于存储大块数据(例如页面)。注意,这个是从1.0.6版本开始支持的。

·CDummyCache:目前dummy缓存并不实现缓存功能。此组件的目的是用于简化那些需要检查缓存可用性的代码。例如,在开发阶段或者服务器尚未支持实际的缓存功能,我们可以使用此缓存组件。当启用了实际的缓存支持后,我们可以切换到使用相应的缓存组件。在这两种情况中,我们可以使用同样的代码Yii::app()->cache->get($key)获取数据片段而不需要担心Yii::app()->cache可能会是null。此组件从1.0.5版开始支持。

提示:由于所有的这些缓存组件均继承自同样的基类CCache,因此无需改变使用缓存的那些代码就可以切换到使用另一种缓存方式。

使用方式:

yii封装了对不同缓存操作的方法,主要集中在CCache。CCache是所有Cache类的基类。所以配置好缓存后可以调用方式很简单:

根据CCache类说明可以看出,常见的缓存操作方法get,set,add,delete,flush

使用多种缓存

main.php 的配置

‘cache’ => array (

‘class’ => ‘system.caching.CFileCache’

),

‘dbcache’ => array (

‘class’ => ‘system.caching.CDbCache’

)

控制器只需用相应的cacheid调用就好

如:Yii::app()->dbcache

memcached缓存的配置

1.下载memcached软件包,解压,把memcached.exe放到随意一个地方,比如:d:/memcached/下。

2. .开始->运行->输入cmd,命令行打开memcached.exe,所在文件夹,输入:memcached.exe -d install 安装

3.输入memcached.exe -d start启动

4.下载php_memcache.dll文件,放到php/ext/文件夹下,并在php.ini中加入extension=php_memcache.dll。

5.打开yii配置文件:config/main.php,在components下添加:

'memcache'=>array( 

       'class'=>'CMemCache', 

       'servers'=>array( 

           array( 

               'host'=>'127.0.0.1', 

               'port'=>11211, 

               'weight'=>60, 

           ), 

           array( 

               'host'=>'127.0.0.1', 

               'port'=>11211, 

               'weight'=>40, 

           ), 

        ), 

 ),

使用:

Yii::app()->memcache->get(id);

Yii::app()->memcache->set(id,value,time);

Yii::app()->cache->deleteValue($key);

一、数据缓存

$value=Yii::app()->cache->get($id);

if($value===false)

{

//因为在缓存中没找到,重新生成$value

//再缓存一下以备下次使用

//Yii::app()->cache->set($id,$value);

}

为一个要缓存的变量选择ID时,确保该ID在应用中是唯一的。不必保证ID在跨应用的情况下保证唯一,因为缓存组件有足够的智能来区分不同应用的缓存ID。要从缓存中删除一个缓存值,调用delete();要清空所有缓存,调用flush()。调用flush()时要非常小心,因为它会把其它应用的缓存也清空。提示:因为CCache实现了ArrayAccess接口,可以像数组一样使用缓存组件。例如:

$cache=Yii::app()->cache;

$cache['var1']=$value1;//相当于:$cache->set('var1',$value1);

$value2=$cache['var2'];//相当于: $value2=$cache->get('var2');

缓存依赖除了过期设置,缓存数据还会因某些依赖条件发生改变而失效。如果我们缓存了某文件的内容,而该文件后来又被更新了,我们应该让缓存中的拷贝失效,从文件中读取最新内容(而不是从缓存)。我们把一个依赖关系表现为一个CCacheDependency或它的子类的实例,调用set()的时候把依赖实例和要缓存的数据一起传入。//缓存将在30秒后过期//也可能因依赖的文件有更新而更快失效Yii::app()->cache->set($id, $value, 30, new CFileCacheDependency('FileName'));如果我们现在调用get()从缓存中获取$value,缓存组件将检查依赖条件。如果有变,我们会得到false值——数据需要重新生成。下面是可用的缓存依赖的简要说明:CFileCacheDependency:该依赖因文件的最近修改时间发生改变而改变。CDirectoryCacheDependency:该依赖因目录(或其子目录)下的任何文件发生改变而改变。CDbCacheDependency:该依赖因指定的SQL语句的查询结果发生改变而改变。CGlobalStateCacheDependency:该依赖因指定的全局状态值发生改变而改变。全局状态是应用中跨请求、跨SESSION的持久变量,它由CApplication::setGlobalState()来定义。CChainedCacheDependency:该依赖因依赖链中的任何一环发生改变而改变。

二、片段缓存  (Fragment Caching)

片段缓存指缓存网页某片段。例如,如果一个页面在表中显示每年的销售摘要,我们可以存储此表在缓存中,减少每次请求需要重新产生的时间。要使用片段缓存,在控制器视图脚本中调用CController::beginCache()和CController::endCache()。这两种方法开始和结束包括的页面内容将被缓存。类似data caching,我们需要一个编号,识别被缓存的片段。...别的HTML内容...

<?phpif($this->beginCache($id)) { ?>

...被缓存的内容...

<?php$this->endCache(); } ?>

...别的HTML内容...

在上面的,如果beginCache()返回false,缓存的内容将此地方自动插入;否则,在if语句内的内容将被执行并在endCache()触发时缓存。

1.缓存选项(Caching Options)

当调用beginCache(),可以提供一个数组由缓存选项组成的作为第二个参数,以自定义片段缓存。事实上为了方便,beginCache()和endCache()方法是COutputCache widget的包装。因此COutputCache的所有属性都可以在缓存选项中初始化。

2.有效期(Duration)

也许是最常见的选项是duration,指定了内容在缓存中多久有效。和CCache::set()过期参数有点类似。下面的代码缓存内容片段最多一小时:...其他HTML内容...<?phpif($this->beginCache($id, array('duration'=>3600))){ ?>

...被缓存的内容...

<?php$this->endCache(); } ?>...其他HTML内容...如果我们不设定期限,它将默认为60,这意味着60秒后缓存内容将无效。

3.依赖(Dependency)

像data caching,内容片段被缓存也可以有依赖。例如,文章的内容被显示取决于文章是否被修改。要指定一个依赖,我们建立了dependency选项,可以是一个实现ICacheDependency的对象或可用于生成依赖对象的配置数组。下面的代码指定片段内容取决lastModified列的值是否变化:...其他HTML内容...

<?php if($this->beginCache($id, array('dependency'=>array(

'class'=>'system.caching.dependencies.CDbCacheDependency',

'sql'=>'SELECT MAX(lastModified) FROM Post')))) { ?>

...被缓存的内容 ...

<?php $this->endCache(); } ?>

...其他 HTML 内容 ...

4.变化(Variation)

缓存的内容可根据一些参数变化。例如,每个人的档案都不一样。缓存的档案内容将根据每个人ID变化。这意味着,当调用beginCache()时将用不同的ID。COutputCache内置了这一特征,程序员不需要编写根据ID变动内容的模式。以下是摘要。varyByRoute:设置此选项为true,缓存的内容将根据route变化。因此,每个控制器和行动的组合将有一个单独的缓存内容。varyBySession:设置此选项为true,缓存的内容将根据sessionID变化。因此,每个用户会话可能会看到由缓存提供的不同内容。varyByParam:设置此选项的数组里的名字,缓存的内容将根据GET参数的值变动。例如,如果一个页面显示文章的内容根据id的GET参数,我们可以指定varyByParam为array('id'),以使我们能够缓存每篇文章内容。如果没有这样的变化,我们只能能够缓存某一文章。这里有问题要讨论:我可以正确使用以下数据调用

if($this->beginCache('good_list_manager',array('duration'=>3600,'varyByParam'=>array('id')))){?>

{

    // ... display the content to be cachedhere

   $this->endCache();

}

但是以下代码不能使用,因为其参数为‘Goods[name]’YII无法正确识别!

if($this->beginCache('good_list_manager',array('duration'=>3600,'varyByParam'=>array("Goods[name]")))

{

    // ... display the content to be cachedhere

   $this->endCache();

}

解决方法:自己建立根据ID变动内容的模式。

if($this->beginCache('good_list_manager_'.$_GET[Goods][name].'_'.$_GET[Goods][bn].'_'.$_GET[Goods][cat_id].'_'.$_GET[Goods][brand_id].'_'.$_GET[Goods][marketable].'_'.$_GET[Goods][cps_status].'_'.$_GET[Goods][is_check],array('duration'=>3600))){?>

{

    // ... display the content to be cachedhere

   $this->endCache();

}

5.请求类型(Request Types)

有时候,我们希望片段缓存只对某些类型的请求启用。例如,对于某张网页上显示表单,我们只想要缓存initiallyrequested表单(通过GET请求)。任何随后显示(通过POST请求)的表单将不被缓存,因为表单可能包含用户输入。要做到这一点,我们可以指定requestTypes选项:

...其他HTML内容...

<?php if($this->beginCache($id,array('requestTypes'=>array('GET')))) { ?>

...被缓存的内容...

<?php $this->endCache(); } ?>

...其他HTML内容...

6.嵌套缓存(Nested Caching)

片段缓存可以嵌套。就是说一个缓存片段附在一个更大的片段缓存里。例如,意见缓存在内部片段缓存,而且它们一起在外部缓存中在文章内容里缓存。

...其他HTML内容...

<?php if($this->beginCache($id1)) { ?>

...外部被缓存内容...

<?php if($this->beginCache($id2)) { ?>

...内部被缓存内容...

<?php $this->endCache(); } ?>

...外部被缓存内容...

<?php $this->endCache(); } ?>

...其他HTML内容...

嵌套缓存可以设定不同的缓存选项。例如,在上面的例子中内部缓存和外部缓存可以设置时间长短不同的持续值。当数据存储在外部缓存无效,内部缓存仍然可以提供有效的内部片段。然而,反之就不行了。如果外部缓存包含有效的数据,它会永远保持缓存副本,即使内容中的内部缓存已经过期。

三、页面缓存

页面缓存指的是缓存整个页面的内容。页面缓存可以发生在不同的地方。例如,通过选择适当的页面头,客户端的浏览器可能会缓存网页浏览有限时间。Web应用程序本身也可以在缓存中存储网页内容。在本节中,我们侧重于后一种办法。页面缓存可以被看作是片段缓存(/doc/guide/caching.fragment)一个特殊情况。由于网页内容是往往通过应用布局来生成,如果我们只是简单的在布局中调用beginCache()和endCache(),将无法正常工作。这是因为布局在CController::render()方法里的加载是在页面内容产生之后。缓存整个页面,我们应该跳过产生网页内容的动作执行。我们可以使用COutputCache作为动作过滤器(/doc/guide/basics.controller#filter)来完成这一任务。下面的代码演示如何配置缓存过滤器:

public function filters()

{

return array(

array(

'system.web.widgets.COutputCache',

'duration'=>100,

'varyByParam'=>array('id'),

),

);

}

上述过滤器配置会使过滤器适用于控制器中的所有行动。我们可能会限制它在一个或几个行动通过使用插件操作器。更多的细节中可以看过滤器(/doc/guide/basics.controller#filter)。提示:我们可以使用COutputCache作为一个过滤器,因为它从CFilterWidget继承过来,这意味着它是一个工具(widget)和一个过滤器。事实上,widge的工作方式和过滤器非常相似:工具widget (过滤器filter)是在action动作里的内容执行前执行,在执行后结束。

四、动态内容(DynamicContent)

当使用fragment caching或page caching,我们常常遇到的这样的情况整个部分的输出除了个别地方都是静态的。例如,帮助页可能会显示静态的帮助信息,而用户名称显示的是当前用户的。解决这个问题,我们可以根据用户名匹配缓存内容,但是这将是我们宝贵空间一个巨大的浪费,因为缓存除了用户名其他大部分内容是相同的。我们还可以把网页切成几个片段并分别缓存,但这种情况会使页面和代码变得非常复杂。更好的方法是使用由CController提供的动态内容dynamic content功能。动态内容是指片段输出即使是在片段缓存包括的内容中也不会被缓存。即使是包括的内容是从缓存中取出,为了使动态内容在所有时间是动态的,每次都得重新生成。出于这个原因,我们要求动态内容通过一些方法或函数生成。调用CController::renderDynamic()在你想的地方插入动态内容。

...别的HTML内容...

<?phpif($this->beginCache($id)) { ?>

...被缓存的片段内容...

<?php$this->renderDynamic($callback); ?>

...被缓存的片段内容...

<?php$this->endCache(); } ?>

...别的HTML内容...

renderDynamic复杂调用形式:$this->renderDynamic('widget','application.extensions.uinfo',array('uid'=>'hahahah!'),true);就相当于$this->widget('application.extensions.uinfo',array('uid'=>'hahahah!'),true);在上面的,$callback指的是有效的PHP回调。它可以是指向当前控制器类的方法或者全局函数的字符串名。它也可以是一个数组名指向一个类的方法。其他任何的参数,将传递到renderDynamic()方法中。回调将返回动态内容而不是仅仅显示它。

编程技巧