YII Framework框架教程之缓存用法详解
本文实例讲述了YIIFramework框架缓存用法。分享给大家供大家参考,具体如下:
缓存的产生原因众所周知。于是YII作为一个高效,好用的框架,不能不支持缓存。所以YII对各种流行的缓存都提供了接口,你可以根据你的需要使用不同的缓存。
1.YII中的缓存介绍
YII中的缓存是通过组件方式定义的,具体在如下目录
/yii_dev/yii/framework/caching#tree
.
├──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
1directory,17files
官方原文解释如下:
Yii提供了不同的缓存组件,可以将缓存数据存储到不同的媒介中。例如,CMemCache组件封装了PHP的memcache扩展并使用内存作为缓存存储媒介。CApcCache组件封装了PHPAPC扩展;而CDbCache组件会将缓存的数据存入数据库。下面是一个可用缓存组件的列表:
CMemCache:使用PHPmemcache扩展.
CApcCache:使用PHPAPC扩展.
CXCache:使用PHPXCache扩展。注意,这个是从1.0.1版本开始支持的。
CEAcceleratorCache:使用PHPEAccelerator扩展.
CDbCache:使用一个数据表存储缓存数据。默认情况下,它将创建并使用在runtime目录下的一个SQLite3数据库。你也可以通过设置其connectionID属性指定一个给它使用的数据库。
CZendDataCache:使用ZendDataCache作为后台缓存媒介。注意,这个是从1.0.4版本开始支持的。
CFileCache:使用文件存储缓存数据。这个特别适合用于存储大块数据(例如页面)。注意,这个是从1.0.6版本开始支持的。
CDummyCache:目前dummy缓存并不实现缓存功能。此组件的目的是用于简化那些需要检查缓存可用性的代码。例如,在开发阶段或者服务器尚未支持实际的缓存功能,我们可以使用此缓存组件。当启用了实际的缓存支持后,我们可以切换到使用相应的缓存组件。在这两种情况中,我们可以使用同样的代码Yii::app()->cache->get($key)获取数据片段而不需要担心Yii::app()->cache可能会是null。此组件从1.0.5版开始支持。
提示:由于所有的这些缓存组件均继承自同样的基类CCache,因此无需改变使用缓存的那些代码就可以切换到使用另一种缓存方式。
缓存可以用于不同的级别。最低级别中,我们使用缓存存储单个数据片段,例如变量,我们将此称为数据缓存(datacaching)。下一个级别中,我们在缓存中存储一个由视图脚本的一部分生成的页面片段。而在最高级别中,我们将整个页面存储在缓存中并在需要时取回。
在接下来的几个小节中,我们会详细讲解如何在这些级别中使用缓存。
注意:按照定义,缓存是一个不稳定的存储媒介。即使没有超时,它也并不确保缓存数据一定存在。因此,不要将缓存作为持久存储器使用。(例如,不要使用缓存存储Session数据)。
2.缓存的配置和调用方式
yii中的缓存主要是通过组件的方式实现的,具体需要配置方式可以通过缓存的类说明进行配置。
通常是指定缓存组件的类
例如apc
'cache'=>array( 'class'=>'system.caching.CApcCache' ),
memcache的配置方式可能是
*array( *'components'=>array( *'cache'=>array( *'class'=>'CMemCache', *'servers'=>array( *array( *'host'=>'server1', *'port'=>11211, *'weight'=>60, *), *array( *'host'=>'server2', *'port'=>11211, *'weight'=>40, *), *), *), *), *)
使用方式:
yii封装了对不同缓存操作的方法,主要集中在CCache。CCache是所有Cache类的基类。所以配置好缓存后可以调用方式很简单:
<?php /** *CCacheisthebaseclassforcacheclasseswithdifferentcachestorageimplementation. * *Adataitemcanbestoredincachebycalling{@linkset}andberetrievedback *laterby{@linkget}.Inbothoperations,akeyidentifyingthedataitemisrequired. *Anexpirationtimeand/oradependencycanalsobespecifiedwhencalling{@linkset}. *Ifthedataitemexpiresorthedependencychanges,calling{@linkget}willnot *returnbackthedataitem. * *Note,bydefinition,cachedoesnotensuretheexistenceofavalue *evenifitdoesnotexpire.Cacheisnotmeanttobeapersistentstorage. * *CCacheimplementstheinterface{@linkICache}withthefollowingmethods: *<ul> *<li>{@linkget}:retrievethevaluewithakey(ifany)fromcache</li> *<li>{@linkset}:storethevaluewithakeyintocache</li> *<li>{@linkadd}:storethevalueonlyifcachedoesnothavethiskey</li> *<li>{@linkdelete}:deletethevaluewiththespecifiedkeyfromcache</li> *<li>{@linkflush}:deleteallvaluesfromcache</li> *</ul> * *Childclassesmustimplementthefollowingmethods: *<ul> *<li>{@linkgetValue}</li> *<li>{@linksetValue}</li> *<li>{@linkaddValue}</li> *<li>{@linkdeleteValue}</li> *<li>{@linkflush}(optional)</li> *</ul> * *CCachealsoimplementsArrayAccesssothatitcanbeusedlikeanarray. * *@authorQiangXue<qiang.xue@gmail.com> *@version$Id:CCache.php30012011-02-2416:42:44Zalexander.makarow$ *@packagesystem.caching *@since1.0 */ abstractclassCCacheextendsCApplicationComponentimplementsICache,ArrayAccess {
根据CCache类说明可以看出,常见的缓存操作方法get,set,add,delete,flush
/** *Retrievesavaluefromcachewithaspecifiedkey. *@paramstring$idakeyidentifyingthecachedvalue *@returnmixedthevaluestoredincache,falseifthevalueisnotinthecache,expiredorthedependencyhaschanged. */ publicfunctionget($id) { if(($value=$this->getValue($this->generateUniqueKey($id)))!==false) { $data=unserialize($value); if(!is_array($data)) returnfalse; if(!($data[1]instanceofICacheDependency)||!$data[1]->getHasChanged()) { Yii::trace('Serving"'.$id.'"fromcache','system.caching.'.get_class($this)); return$data[0]; } } returnfalse; } /** *Retrievesmultiplevaluesfromcachewiththespecifiedkeys. *Somecaches(suchasmemcache,apc)allowretrievingmultiplecachedvaluesatonetime, *whichmayimprovetheperformancesinceitreducesthecommunicationcost. *Incaseacachedoesn'tsupportthisfeaturenatively,itwillbesimulatedbythismethod. *@paramarray$idslistofkeysidentifyingthecachedvalues *@returnarraylistofcachedvaluescorrespondingtothespecifiedkeys.Thearray *isreturnedintermsof(key,value)pairs. *Ifavalueisnotcachedorexpired,thecorrespondingarrayvaluewillbefalse. *@since1.0.8 */ publicfunctionmget($ids) { $uniqueIDs=array(); $results=array(); foreach($idsas$id) { $uniqueIDs[$id]=$this->generateUniqueKey($id); $results[$id]=false; } $values=$this->getValues($uniqueIDs); foreach($uniqueIDsas$id=>$uniqueID) { if(!isset($values[$uniqueID])) continue; $data=unserialize($values[$uniqueID]); if(is_array($data)&&(!($data[1]instanceofICacheDependency)||!$data[1]->getHasChanged())) { Yii::trace('Serving"'.$id.'"fromcache','system.caching.'.get_class($this)); $results[$id]=$data[0]; } } return$results; } /** *Storesavalueidentifiedbyakeyintocache. *Ifthecachealreadycontainssuchakey,theexistingvalueand *expirationtimewillbereplacedwiththenewones. * *@paramstring$idthekeyidentifyingthevaluetobecached *@parammixed$valuethevaluetobecached *@paraminteger$expirethenumberofsecondsinwhichthecachedvaluewillexpire.0meansneverexpire. *@paramICacheDependency$dependencydependencyofthecacheditem.Ifthedependencychanges,theitemislabeledinvalid. *@returnbooleantrueifthevalueissuccessfullystoredintocache,falseotherwise */ publicfunctionset($id,$value,$expire=0,$dependency=null) { Yii::trace('Saving"'.$id.'"tocache','system.caching.'.get_class($this)); if($dependency!==null) $dependency->evaluateDependency(); $data=array($value,$dependency); return$this->setValue($this->generateUniqueKey($id),serialize($data),$expire); } /** *Storesavalueidentifiedbyakeyintocacheifthecachedoesnotcontainthiskey. *Nothingwillbedoneifthecachealreadycontainsthekey. *@paramstring$idthekeyidentifyingthevaluetobecached *@parammixed$valuethevaluetobecached *@paraminteger$expirethenumberofsecondsinwhichthecachedvaluewillexpire.0meansneverexpire. *@paramICacheDependency$dependencydependencyofthecacheditem.Ifthedependencychanges,theitemislabeledinvalid. *@returnbooleantrueifthevalueissuccessfullystoredintocache,falseotherwise */ publicfunctionadd($id,$value,$expire=0,$dependency=null) { Yii::trace('Adding"'.$id.'"tocache','system.caching.'.get_class($this)); if($dependency!==null) $dependency->evaluateDependency(); $data=array($value,$dependency); return$this->addValue($this->generateUniqueKey($id),serialize($data),$expire); } /** *Deletesavaluewiththespecifiedkeyfromcache *@paramstring$idthekeyofthevaluetobedeleted *@returnbooleanifnoerrorhappensduringdeletion */ publicfunctiondelete($id) { Yii::trace('Deleting"'.$id.'"fromcache','system.caching.'.get_class($this)); return$this->deleteValue($this->generateUniqueKey($id)); } /** *Deletesallvaluesfromcache. *Becarefulofperformingthisoperationifthecacheissharedbymultipleapplications. *@returnbooleanwhethertheflushoperationwassuccessful. */ publicfunctionflush() { Yii::trace('Flushingcache','system.caching.'.get_class($this)); return$this->flushValues(); }
即:
Yii::app()->cache->xxx
xxx对应具体的方法。
例如:
$id='key1'; $value='cachevalue'; Yii::app()->cache->add($id,$value); var_dump(Yii::app()->cache->get($id));
下面是yii官方给出的几种缓存方式的使用说明,这里就麻木不仁,照搬了
3.缓存的使用:数据缓存
数据缓存
数据缓存即存储一些PHP变量到缓存中,以后再从缓存中取出来。出于此目的,缓存组件的基类CCache提供了两个最常用的方法:set()和get()。
要在缓存中存储一个变量$value,我们选择一个唯一ID并调用set()存储它:
Yii::app()->cache->set($id,$value);
缓存的数据将一直留在缓存中,除非它由于某些缓存策略(例如缓存空间已满,旧的数据被删除)而被清除。要改变这种行为,我们可以在调用set()的同时提供一个过期参数,这样在设定的时间段之后,缓存数据将被清除:
//值$value在缓存中最多保留30秒 Yii::app()->cache->set($id,$value,30);
稍后当我们需要访问此变量时(在同一个或不同的Web请求中),就可以通过ID调用get()从缓存中将其取回。如果返回的是false,表示此值在缓存中不可用,我们应该重新生成它。
$value=Yii::app()->cache->get($id); if($value===false) { //因为在缓存中没找到$value,重新生成它, //并将它存入缓存以备以后使用: //Yii::app()->cache->set($id,$value); }
为要存入缓存的变量选择ID时,要确保此ID对应用中所有其他存入缓存的变量是唯一的。而在不同的应用之间,这个ID不需要是唯一的。缓存组件具有足够的智慧区分不同应用中的ID。
一些缓存存储器,例如MemCache,APC,支持以批量模式获取多个缓存值。这可以减少获取缓存数据时带来的开销。从版本1.0.8起,Yii提供了一个新的名为mget()的方法。它可以利用此功能。如果底层缓存存储器不支持此功能,mget()依然可以模拟实现它。
要从缓存中清除一个缓存值,调用delete();要清楚缓存中的所有数据,调用flush()。当调用flush()时一定要小心,因为它会同时清除其他应用中的缓存。
提示:由于CCache实现了ArrayAccess,缓存组件也可以像一个数组一样使用。下面是几个例子:
$cache=Yii::app()->cache; $cache['var1']=$value1;//相当于:$cache->set('var1',$value1); $value2=$cache['var2'];//相当于:$value2=$cache->get('var2');
1.缓存依赖
除了过期设置,缓存数据也可能会因为依赖条件发生变化而失效。例如,如果我们缓存了某些文件的内容,而这些文件发生了改变,我们就应该让缓存的数据失效,并从文件中读取最新内容而不是从缓存中读取。
我们将一个依赖关系表现为一个CCacheDependency或其子类的实例。当调用set()时,我们连同要缓存的数据将其一同传入。
//此值将在30秒后失效 //也可能因依赖的文件发生了变化而更快失效 Yii::app()->cache->set($id,$value,30,newCFileCacheDependency('FileName'));
现在如果我们通过调用get()从缓存中获取$value,依赖关系将被检查,如果发生改变,我们将会得到一个false值,表示数据需要被重新生成。
如下是可用的缓存依赖的简要说明:
CFileCacheDependency:如果文件的最后修改时间发生改变,则依赖改变。
CDirectoryCacheDependency:如果目录和其子目录中的文件发生改变,则依赖改变。
CDbCacheDependency:如果指定SQL语句的查询结果发生改变,则依赖改变。
CGlobalStateCacheDependency:如果指定的全局状态发生改变,则依赖改变。全局状态是应用中的一个跨请求,跨会话的变量。它是通过CApplication::setGlobalState()定义的。
CChainedCacheDependency:如果链中的任何依赖发生改变,则此依赖改变。
CExpressionDependency:如果指定的PHP表达式的结果发生改变,则依赖改变。此类从版本1.0.4起可用。
4.缓存的使用:片段缓存
片段缓存(FragmentCaching)
片段缓存指缓存网页某片段。例如,如果一个页面在表中显示每年的销售摘要,我们可以存储此表在缓存中,减少每次请求需要重新产生的时间。
要使用片段缓存,在控制器视图脚本中调用CController::beginCache()和CController::endCache()。这两种方法开始和结束包括的页面内容将被缓存。类似datacaching,我们需要一个编号,识别被缓存的片段。
...别的HTML内容... <?phpif($this->beginCache($id)){?> ...被缓存的内容... <?php$this->endCache();}?> ...别的HTML内容...
在上面的,如果beginCache()返回false,缓存的内容将此地方自动插入;否则,在if语句内的内容将被执行并在endCache()触发时缓存。
1.缓存选项(CachingOptions)
当调用beginCache(),可以提供一个数组由缓存选项组成的作为第二个参数,以自定义片段缓存。事实上为了方便,beginCache()和endCache()方法是[COutputCache]widget的包装。因此COutputCache的所有属性都可以在缓存选项中初始化。
有效期(Duration)
也许是最常见的选项是duration,指定了内容在缓存中多久有效。和CCache::set()过期参数有点类似。下面的代码缓存内容片段最多一小时:
...其他HTML内容... <?phpif($this->beginCache($id,array('duration'=>3600))){?> ...被缓存的内容... <?php$this->endCache();}?> ...其他HTML内容...
如果我们不设定期限,它将默认为60,这意味着60秒后缓存内容将无效。
依赖(Dependency)
像datacaching,内容片段被缓存也可以有依赖。例如,文章的内容被显示取决于文章是否被修改。
要指定一个依赖,我们建立了dependency选项,可以是一个实现[ICacheDependency]的对象或可用于生成依赖对象的配置数组。下面的代码指定片段内容取决于lastModified列的值是否变化:
...其他HTML内容... <?phpif($this->beginCache($id,array('dependency'=>array( 'class'=>'system.caching.dependencies.CDbCacheDependency', 'sql'=>'SELECTMAX(lastModified)FROMPost')))){?> ...被缓存的内容... <?php$this->endCache();}?> ...其他HTML内容...
变化(Variation)
缓存的内容可根据一些参数变化。例如,每个人的档案都不一样。缓存的档案内容将根据每个人ID变化。这意味着,当调用beginCache()时将用不同的ID。
COutputCache内置了这一特征,程序员不需要编写根据ID变动内容的模式。以下是摘要。
varyByRoute:设置此选项为true,缓存的内容将根据route变化。因此,每个控制器和行动的组合将有一个单独的缓存内容。
varyBySession:设置此选项为true,缓存的内容将根据sessionID变化。因此,每个用户会话可能会看到由缓存提供的不同内容。
varyByParam:设置此选项的数组里的名字,缓存的内容将根据GET参数的值变动。例如,如果一个页面显示文章的内容根据id的GET参数,我们可以指定varyByParam为array('id'),以使我们能够缓存每篇文章内容。如果没有这样的变化,我们只能能够缓存某一文章。
varyByExpression:bysettingthisoptiontoaPHPexpression,wecanmakethecachedcontenttobevariatedaccordingtotheresultofthisPHPexpression.Thisoptionhasbeenavailablesinceversion1.0.4.
RequestTypes
有时候,我们希望片段缓存只对某些类型的请求启用。例如,对于某张网页上显示表单,我们只想要缓存initiallyrequested表单(通过GET请求)。任何随后显示(通过POST请求)的表单将不被缓存,因为表单可能包含用户输入。要做到这一点,我们可以指定requestTypes选项:
...其他HTML内容... <?phpif($this->beginCache($id,array('requestTypes'=>array('GET')))){?> ...被缓存的内容... <?php$this->endCache();}?> ...其他HTML内容...
2.嵌套缓存(NestedCaching)
片段缓存可以嵌套。就是说一个缓存片段附在一个更大的片段缓存里。例如,意见缓存在内部片段缓存,而且它们一起在外部缓存中在文章内容里缓存。
...其他HTML内容... <?phpif($this->beginCache($id1)){?> ...外部被缓存内容... <?phpif($this->beginCache($id2)){?> ...内部被缓存内容... <?php$this->endCache();}?> ...外部被缓存内容... <?php$this->endCache();}?> ...其他HTML内容...
嵌套缓存可以设定不同的缓存选项。例如,在上面的例子中内部缓存和外部缓存可以设置时间长短不同的持续值。当数据存储在外部缓存无效,内部缓存仍然可以提供有效的内部片段。然而,反之就不行了。如果外部缓存包含有效的数据,它会永远保持缓存副本,即使内容中的内部缓存已经过期。
5.缓存的使用:页面缓存
页面缓存
页面缓存指的是缓存整个页面的内容。页面缓存可以发生在不同的地方。例如,通过选择适当的页面头,客户端的浏览器可能会缓存网页浏览有限时间。Web应用程序本身也可以在缓存中存储网页内容。在本节中,我们侧重于后一种办法。
页面缓存可以被看作是片段缓存一个特殊情况。由于网页内容是往往通过应用布局来生成,如果我们只是简单的在布局中调用beginCache()和endCache(),将无法正常工作。这是因为布局在CController::render()方法里的加载是在页面内容产生之后。
如果想要缓存整个页面,我们应该跳过产生网页内容的动作执行。我们可以使用COutputCache作为动作过滤器来完成这一任务。下面的代码演示如何配置缓存过滤器:
publicfunctionfilters() { returnarray( array( 'COutputCache', 'duration'=>100, 'varyByParam'=>array('id'), ), ); }
上述过滤器配置会使过滤器适用于控制器中的所有行动。我们可能会限制它在一个或几个行动通过使用插件操作器。更多的细节中可以看过滤器。
Tip:我们可以使用COutputCache作为一个过滤器,因为它从CFilterWidget继承过来,这意味着它是一个工具(widget)和一个过滤器。事实上,widget的工作方式和过滤器非常相似:工具widget(过滤器filter)是在action动作里的内容执行前执行,在执行后结束。
6.缓存的使用:动态内容
动态内容(DynamicContent)
当使用fragmentcaching或pagecaching,我们常常遇到的这样的情况整个部分的输出除了个别地方都是静态的。例如,帮助页可能会显示静态的帮助信息,而用户名称显示的是当前用户的。
解决这个问题,我们可以根据用户名匹配缓存内容,但是这将是我们宝贵空间一个巨大的浪费,因为缓存除了用户名其他大部分内容是相同的。我们还可以把网页切成几个片段并分别缓存,但这种情况会使页面和代码变得非常复杂。更好的方法是使用由[CController]提供的动态内容dynamiccontent功能。
动态内容是指片段输出即使是在片段缓存包括的内容中也不会被缓存。即使是包括的内容是从缓存中取出,为了使动态内容在所有时间是动态的,每次都得重新生成。出于这个原因,我们要求动态内容通过一些方法或函数生成。
调用CController::renderDynamic()在你想的地方插入动态内容。
...别的HTML内容... <?phpif($this->beginCache($id)){?> ...被缓存的片段内容... <?php$this->renderDynamic($callback);?> ...被缓存的片段内容... <?php$this->endCache();}?> ...别的HTML内容...
在上面的,$callback指的是有效的PHP回调。它可以是指向当前控制器类的方法或者全局函数的字符串名。它也可以是一个数组名指向一个类的方法。其他任何的参数,将传递到renderDynamic()方法中。回调将返回动态内容而不是仅仅显示它。
更多关于Yii相关内容感兴趣的读者可查看本站专题:《Yii框架入门及常用技巧总结》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php日期与时间用法总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。