COutputCache
包 | system.web.widgets |
---|---|
继承 | class COutputCache » CFilterWidget » CWidget » CBaseController » CComponent |
实现 | IFilter |
源自 | 1.0 |
版本 | $Id: COutputCache.php 3515 2011-12-28 12:29:24Z mdomba $ |
源码 | framework/web/widgets/COutputCache.php |
如果需要显示的输出在缓存中可用,缓存中的版本将 代替真实的版本被显示,通过这种方式可以节省生成 原始输出的时间。
因为COutputCache是从CFilterWidget扩展而来,所以它可以 用作过滤器(为动作缓存)或小物件(为片段缓存)。 在第二种用法中,通常使用快捷方式CBaseController::beginCache()和 CBaseController::endCache()来代替,例如下面的视图文件:
if($this->beginCache('cacheName',array('property1'=>'value1',...)) { // ... 在此处显示缓存的内容 $this->endCache(); }
COutputCache必须与一个通过cacheID指定的缓存应用组件共同工作。 如果该缓存应用组件不可用,COutputCache也将被禁用。
有两个因素决定一个缓存的内容是否有效: duration 以及缓存的 dependency。 前者指定了数据可以在缓存中维持有效的秒数(默认值是 60秒),而后者指定了缓存数据的依赖项。如果一个 依赖项发生改变,(例如,数据库中的相关数据被更新), 缓存中的数据将不再有效。 参见CCacheDependency以了解更多关于缓存依赖的细节。
有时候,为了执行一个确定的请求类型,有必要关闭输出缓存。 例如,我们仅希望一个表单在初次被请求的时候被缓存,随后对 此表单的显示将不希望使用缓存,因为它包含了用户的输入。 我们可以设置requestTypes为
array('GET')
以达到这一目的。
通过一些参数的设置,可以从缓存中得到不同的内容。 COutputCache支持四种变化:
- varyByRoute: 这个参数指定缓存内容是否 随着请求的路由(控制器与动作)而变化。
- varyByParam: 这个参数指定了一个GET参数 的名字列表并使用相应的值来决定缓存数据的版本。
- varyBySession: 这个参数指定缓存内容是 否随着用户会话而变化。
- varyByExpression: 这个参数指定缓存内容 是否随着指定的PHP表达式的结果而变化。
公共属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
actionPrefix | string | actions的ID的前缀。 当微件在CController::actions中声明了 动作提供者,可以为其动作的ID指定前缀以区别 于别的微件或控制器。当微件用于控制器 的视图中时,必须配置同样的前缀。 | CWidget |
cacheID | string | 缓存应用组件的ID。默认值是“cache”(主要的缓存应用组件)。 | COutputCache |
controller | CController | 返回此微件所属的控制器。 | CWidget |
dependency | mixed | 缓存内容依赖的依赖项。
这个值可以是一个实现了ICacheDependency接口的对象,
或一个指定了依赖项对象的配置数组。例如:
array( 'class'=>'CDbCacheDependency', 'sql'=>'SELECT MAX(lastModified) FROM Post', )将使缓存输出依赖于所有帖子的最后修改时间。 如果任何一个帖子的修改时间发生了变化,缓存内容将被撤销。 |
COutputCache |
duration | integer | 数据在缓存中保存的秒数。默认值是60秒。
如果设置为0,已存在的缓存内容将被从缓存中移除。
如果设置为负数,缓存将被禁用(任何已保存在缓存中的内容
将被保留)。
注意:如果缓存依赖发生了改变或缓存空间到达上限, 缓存中较早的数据将被移除。 |
COutputCache |
id | string | 返回此微件的ID。如果需要的话,将生产一个新的ID并将其返回。 | CWidget |
isContentCached | boolean | 内容是否已在缓存中存在 | COutputCache |
isFilter | boolean | 这个widget是否作为一个过滤器使用。 | CFilterWidget |
owner | CBaseController | 返回此微件的所有者或创建者。 | CWidget |
requestTypes | array | 请求类型的列表(例如,GET,POST)指明仅何种类型的缓存可用。 默认值是null,表示所有请求类型。 | COutputCache |
skin | mixed | 微件使用的皮肤的名称。默认为“default”。 如果此属性设置为false,微件将不会有皮肤被使用。 | CWidget |
stopAction | boolean | 当这个widget用作一个过滤器时是否停止动作的执行。 此属性应当仅在CWidget::init方法中进行改变。 默认值是false,表示动作将会被执行。 | CFilterWidget |
varyByExpression | string | 一个PHP表达式,它的结果用于缓存键值的计算中。 通过设置此属性,每个不同的表达式结果可以使用不同的缓存数据 来产生输出。 这个表达式也可以是一个有效的PHP回调函数, 包括类名和方法名(array(ClassName/Object, MethodName)), 或者匿名函数(PHP 5. | COutputCache |
varyByParam | array | GET参数的列表,它参与到缓存键值的计算中。 通过设置此属性,每个不同的GET参数值的集合可以使用不同 的缓存数据来产生输出。 | COutputCache |
varyByRoute | boolean | 缓存内容是否根据路由进行区分。 一个路由是由请求的控制器ID和动作ID组成的。 默认值是true。 | COutputCache |
varyBySession | boolean | 缓存内容是否根据用户会话进行区分。默认值是false。 | COutputCache |
viewPath | string | 返回包含此微件所需的视图文件的路径。 | CWidget |
受保护属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
baseCacheKey | string | 计算基本缓存键值。 | COutputCache |
cache | ICache | 用于缓存内容的缓存器 | COutputCache |
cacheKey | string | 计算机缓存键值。 | COutputCache |
公共方法
受保护方法
方法 | 描述 | 定义在 |
---|---|---|
checkContentCache() | 在缓存中查找内容。 | COutputCache |
getBaseCacheKey() | 计算基本缓存键值。 | COutputCache |
getCache() | 返回用于缓存内容的缓存器 | COutputCache |
getCacheKey() | 计算机缓存键值。 | COutputCache |
replayActions() | 重做被记录的方法调用的集合。 | COutputCache |
属性详细
计算基本缓存键值。 计算出的键值在getCacheKey可以进一步变动。 派生类如果需要更多的变化,可以覆盖此方法。
用于缓存内容的缓存器
缓存应用组件的ID。默认值是“cache”(主要的缓存应用组件)。
计算机缓存键值。 键值在getBaseCacheKey其他要素的基础上进行计算,包括 varyByRoute, varyByParam 和 varyBySession。
缓存内容依赖的依赖项。 这个值可以是一个实现了ICacheDependency接口的对象, 或一个指定了依赖项对象的配置数组。例如:
array( 'class'=>'CDbCacheDependency', 'sql'=>'SELECT MAX(lastModified) FROM Post', )将使缓存输出依赖于所有帖子的最后修改时间。 如果任何一个帖子的修改时间发生了变化,缓存内容将被撤销。
数据在缓存中保存的秒数。默认值是60秒。
如果设置为0,已存在的缓存内容将被从缓存中移除。
如果设置为负数,缓存将被禁用(任何已保存在缓存中的内容
将被保留)。
注意:如果缓存依赖发生了改变或缓存空间到达上限,
缓存中较早的数据将被移除。
内容是否已在缓存中存在
请求类型的列表(例如,GET,POST)指明仅何种类型的缓存可用。 默认值是null,表示所有请求类型。
一个PHP表达式,它的结果用于缓存键值的计算中。 通过设置此属性,每个不同的表达式结果可以使用不同的缓存数据 来产生输出。 这个表达式也可以是一个有效的PHP回调函数, 包括类名和方法名(array(ClassName/Object, MethodName)), 或者匿名函数(PHP 5.3.0+)。这个函数/方法签名如下:
function foo($cache) { ... }这儿$cache指向缓存输出组件。
GET参数的列表,它参与到缓存键值的计算中。 通过设置此属性,每个不同的GET参数值的集合可以使用不同 的缓存数据来产生输出。
缓存内容是否根据路由进行区分。 一个路由是由请求的控制器ID和动作ID组成的。 默认值是true。
缓存内容是否根据用户会话进行区分。默认值是false。
方法详细
protected boolean checkContentCache()
| ||
{return} | boolean | 内容是否在缓存中找到。 |
protected function checkContentCache()
{
if((empty($this->requestTypes) || in_array(Yii::app()->getRequest()->getRequestType(),$this->requestTypes))
&& ($this->_cache=$this->getCache())!==null)
{
if($this->duration>0 && ($data=$this->_cache->get($this->getCacheKey()))!==false)
{
$this->_content=$data[0];
$this->_actions=$data[1];
return true;
}
if($this->duration==0)
$this->_cache->delete($this->getCacheKey());
if($this->duration<=0)
$this->_cache=null;
}
return false;
}
在缓存中查找内容。
public boolean filter(CFilterChain $filterChain)
| ||
$filterChain | CFilterChain | 将被应用到动作的过滤器的列表 |
{return} | boolean | 在这个过滤器执行之后是否停止过滤处理。默认值是false。 |
public function filter($filterChain)
{
if(!$this->getIsContentCached())
$filterChain->run();
$this->run();
}
在动作被运行前执行过滤。 如果需要前置过滤,那么派生类应当覆盖此方法。
protected string getBaseCacheKey()
| ||
{return} | string | 没有变化的基本缓存键值。 |
protected function getBaseCacheKey()
{
return self::CACHE_KEY_PREFIX.$this->getId().'.';
}
计算基本缓存键值。 计算出的键值在getCacheKey可以进一步变动。 派生类如果需要更多的变化,可以覆盖此方法。
protected ICache getCache()
| ||
{return} | ICache | 用于缓存内容的缓存器 |
protected function getCache()
{
return Yii::app()->getComponent($this->cacheID);
}
protected string getCacheKey()
| ||
{return} | string | 缓存键值 |
protected function getCacheKey()
{
if($this->_key!==null)
return $this->_key;
else
{
$key=$this->getBaseCacheKey().'.';
if($this->varyByRoute)
{
$controller=$this->getController();
$key.=$controller->getUniqueId().'/';
if(($action=$controller->getAction())!==null)
$key.=$action->getId();
}
$key.='.';
if($this->varyBySession)
$key.=Yii::app()->getSession()->getSessionID();
$key.='.';
if(is_array($this->varyByParam) && isset($this->varyByParam[0]))
{
$params=array();
foreach($this->varyByParam as $name)
{
if(isset($_GET[$name]))
$params[$name]=$_GET[$name];
else
$params[$name]='';
}
$key.=serialize($params);
}
$key.='.';
if($this->varyByExpression!==null)
$key.=$this->evaluateExpression($this->varyByExpression);
$key.='.';
return $this->_key=$key;
}
}
计算机缓存键值。 键值在getBaseCacheKey其他要素的基础上进行计算,包括 varyByRoute, varyByParam 和 varyBySession。
public boolean getIsContentCached()
| ||
{return} | boolean | 内容是否已在缓存中存在 |
public function getIsContentCached()
{
if($this->_contentCached!==null)
return $this->_contentCached;
else
return $this->_contentCached=$this->checkContentCache();
}
public void init()
|
public function init()
{
if($this->getIsContentCached())
$this->replayActions();
else if($this->_cache!==null)
{
$this->getController()->getCachingStack()->push($this);
ob_start();
ob_implicit_flush(false);
}
}
标志内容缓存的开始。 显示在此方法之后,endCache()方法之前的内容 将被获取并保存在缓存中。 如果可用的内容在缓存中已存在则此方法什么也不会做。
public void recordAction(string $context, string $method, array $params)
| ||
$context | string | 控制器的一个属性名字。此属性指向一个对象, 它的方法可以被记录。如果为空表示此控制器本身。 |
$method | string | 方法的名字 |
$params | array | 传递给方法的参数 |
public function recordAction($context,$method,$params)
{
$this->_actions[]=array($context,$method,$params);
}
当输出缓存有效时记录一个方法调用。 当内容是由输出缓存提供时,记录方法将被 重调用。
protected void replayActions()
|
protected function replayActions()
{
if(empty($this->_actions))
return;
$controller=$this->getController();
$cs=Yii::app()->getClientScript();
foreach($this->_actions as $action)
{
if($action[0]==='clientScript')
$object=$cs;
else if($action[0]==='')
$object=$controller;
else
$object=$controller->{$action[0]};
if(method_exists($object,$action[1]))
call_user_func_array(array($object,$action[1]),$action[2]);
else if($action[0]==='' && function_exists($action[1]))
call_user_func_array($action[1],$action[2]);
else
throw new CException(Yii::t('yii','Unable to replay the action "{object}.{method}". The method does not exist.',
array('object'=>$action[0],
'method'=>$action[1])));
}
}
重做被记录的方法调用的集合。
public void run()
|
public function run()
{
if($this->getIsContentCached())
{
if($this->getController()->isCachingStackEmpty())
echo $this->getController()->processDynamicOutput($this->_content);
else
echo $this->_content;
}
else if($this->_cache!==null)
{
$this->_content=ob_get_clean();
$this->getController()->getCachingStack()->pop();
$data=array($this->_content,$this->_actions);
if(is_array($this->dependency))
$this->dependency=Yii::createComponent($this->dependency);
$this->_cache->set($this->getCacheKey(),$data,$this->duration,$this->dependency);
if($this->getController()->isCachingStackEmpty())
echo $this->getController()->processDynamicOutput($this->_content);
else
echo $this->_content;
}
}
标志内容缓存的结束。 显示在此方法之前,init()方法之后的内容 将被获取并保存在缓存中。 如果可用的内容在缓存中已存在则此方法什么也不会做。