COutputCache


system.web.widgets
继承 class COutputCache » CFilterWidget » CWidget » CBaseController » CComponent
实现 IFilter
源自 1.0
版本 $Id: COutputCache.php 3515 2011-12-28 12:29:24Z mdomba $
源码
COutputCache 使一个动作或视图片段生成的输出缓冲可用。

如果需要显示的输出在缓存中可用,缓存中的版本将 代替真实的版本被显示,通过这种方式可以节省生成 原始输出的时间。

因为COutputCache是从CFilterWidget扩展而来,所以它可以 用作过滤器(为动作缓存)或小物件(为片段缓存)。 在第二种用法中,通常使用快捷方式CBaseController::beginCache()CBaseController::endCache()来代替,例如下面的视图文件:
if($this->beginCache('cacheName',array('property1'=>'value1',...))
{
    // ... 在此处显示缓存的内容
   $this->endCache();
}


COutputCache必须与一个通过cacheID指定的缓存应用组件共同工作。 如果该缓存应用组件不可用,COutputCache也将被禁用。

有两个因素决定一个缓存的内容是否有效: duration 以及缓存的 dependency。 前者指定了数据可以在缓存中维持有效的秒数(默认值是 60秒),而后者指定了缓存数据的依赖项。如果一个 依赖项发生改变,(例如,数据库中的相关数据被更新), 缓存中的数据将不再有效。 参见CCacheDependency以了解更多关于缓存依赖的细节。

有时候,为了执行一个确定的请求类型,有必要关闭输出缓存。 例如,我们仅希望一个表单在初次被请求的时候被缓存,随后对 此表单的显示将不希望使用缓存,因为它包含了用户的输入。 我们可以设置requestTypesarray('GET')以达到这一目的。

通过一些参数的设置,可以从缓存中得到不同的内容。 COutputCache支持四种变化:
  • varyByRoute: 这个参数指定缓存内容是否 随着请求的路由(控制器与动作)而变化。
  • varyByParam: 这个参数指定了一个GET参数 的名字列表并使用相应的值来决定缓存数据的版本。
  • varyBySession: 这个参数指定缓存内容是 否随着用户会话而变化。
  • varyByExpression: 这个参数指定缓存内容 是否随着指定的PHP表达式的结果而变化。
要实现更高级的变化,可以覆盖getBaseCacheKey()方法。

公共属性

属性 类型 描述 定义在
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

公共方法

方法 描述 定义在
__call() 如果类中没有调的方法名,则调用这个方法。 CComponent
__construct() 构造器。 CFilterWidget
__get() 返回一个属性值、一个事件处理程序列表或一个行为名称。 CComponent
__isset() 检查一个属性是否为null。 CComponent
__set() 设置一个组件的属性值。 CComponent
__unset() 设置一个组件的属性为null。 CComponent
actions() 返回此widget使用的动作的列表。 CWidget
asa() 返回这个名字的行为对象。 CComponent
attachBehavior() 附加一个行为到组件。 CComponent
attachBehaviors() 附加一个行为列表到组件。 CComponent
attachEventHandler() 为事件附加一个事件处理程序。 CComponent
beginCache() Begins fragment caching. CBaseController
beginClip() Begins recording a clip. CBaseController
beginContent() Begins the rendering of content that is to be decorated by the specified view. CBaseController
beginWidget() Creates a widget and executes it. CBaseController
canGetProperty() 确定属性是否可读。 CComponent
canSetProperty() 确定属性是否可写。 CComponent
createWidget() Creates a widget and initializes it. CBaseController
detachBehavior() 从组件中分离一个行为。 CComponent
detachBehaviors() 从组件中分离所有行为。 CComponent
detachEventHandler() 分离一个存在的事件处理程序。 CComponent
disableBehavior() 禁用一个附加行为。 CComponent
disableBehaviors() 禁用组件附加的所有行为。 CComponent
enableBehavior() 启用一个附加行为。 CComponent
enableBehaviors() 启用组件附加的所有行为。 CComponent
endCache() Ends fragment caching. CBaseController
endClip() Ends recording a clip. CBaseController
endContent() Ends the rendering of content. CBaseController
endWidget() Ends the execution of the named widget. CBaseController
evaluateExpression() 计算一个PHP表达式,或根据组件上下文执行回调。 CComponent
filter() 在动作被运行前执行过滤。 COutputCache
getController() 返回此微件所属的控制器。 CWidget
getEventHandlers() 返回一个事件的附加处理程序列表。 CComponent
getId() 返回此微件的ID。如果需要的话,将生产一个新的ID并将其返回。 CWidget
getIsContentCached() 检查内容是否已在缓存中存在 COutputCache
getIsFilter() 检查这个widget是否作为一个过滤器使用。 CFilterWidget
getOwner() 返回此微件的所有者或创建者。 CWidget
getViewFile() 根据视图名查找视图文件。 CWidget
getViewPath() 返回包含此微件所需的视图文件的路径。 CWidget
hasEvent() 确定一个事件是否定义。 CComponent
hasEventHandler() 检查事件是否有附加的处理程序。 CComponent
hasProperty() 确定属性是否被定义。 CComponent
init() 标志内容缓存的开始。 COutputCache
raiseEvent() 发起一个事件。 CComponent
recordAction() 当输出缓存有效时记录一个方法调用。 COutputCache
render() 渲染一个视图。 CWidget
renderFile() Renders a view file. CBaseController
renderInternal() Renders a view file. CBaseController
run() 标志内容缓存的结束。 COutputCache
setId() 设置此微件的ID。 CWidget
widget() Creates a widget and executes it. CBaseController

受保护方法

方法 描述 定义在
checkContentCache() 在缓存中查找内容。 COutputCache
getBaseCacheKey() 计算基本缓存键值。 COutputCache
getCache() 返回用于缓存内容的缓存器 COutputCache
getCacheKey() 计算机缓存键值。 COutputCache
replayActions() 重做被记录的方法调用的集合。 COutputCache

属性详细

baseCacheKey 属性 只读
protected string getBaseCacheKey()

计算基本缓存键值。 计算出的键值在getCacheKey可以进一步变动。 派生类如果需要更多的变化,可以覆盖此方法。

cache 属性 只读
protected ICache getCache()

用于缓存内容的缓存器

cacheID 属性
public string $cacheID;

缓存应用组件的ID。默认值是“cache”(主要的缓存应用组件)。

cacheKey 属性 只读
protected string getCacheKey()

计算机缓存键值。 键值在getBaseCacheKey其他要素的基础上进行计算,包括 varyByRoute, varyByParamvaryBySession

dependency 属性
public mixed $dependency;

缓存内容依赖的依赖项。 这个值可以是一个实现了ICacheDependency接口的对象, 或一个指定了依赖项对象的配置数组。例如:

array(
    'class'=>'CDbCacheDependency',
    'sql'=>'SELECT MAX(lastModified) FROM Post',
)
将使缓存输出依赖于所有帖子的最后修改时间。 如果任何一个帖子的修改时间发生了变化,缓存内容将被撤销。
duration 属性
public integer $duration;

数据在缓存中保存的秒数。默认值是60秒。 如果设置为0,已存在的缓存内容将被从缓存中移除。 如果设置为负数,缓存将被禁用(任何已保存在缓存中的内容 将被保留)。

注意:如果缓存依赖发生了改变或缓存空间到达上限, 缓存中较早的数据将被移除。

isContentCached 属性 只读
public boolean getIsContentCached()

内容是否已在缓存中存在

requestTypes 属性
public array $requestTypes;

请求类型的列表(例如,GET,POST)指明仅何种类型的缓存可用。 默认值是null,表示所有请求类型。

varyByExpression 属性
public string $varyByExpression;

一个PHP表达式,它的结果用于缓存键值的计算中。 通过设置此属性,每个不同的表达式结果可以使用不同的缓存数据 来产生输出。 这个表达式也可以是一个有效的PHP回调函数, 包括类名和方法名(array(ClassName/Object, MethodName)), 或者匿名函数(PHP 5.3.0+)。这个函数/方法签名如下:

function foo($cache) { ... }
这儿$cache指向缓存输出组件。
varyByParam 属性
public array $varyByParam;

GET参数的列表,它参与到缓存键值的计算中。 通过设置此属性,每个不同的GET参数值的集合可以使用不同 的缓存数据来产生输出。

varyByRoute 属性
public boolean $varyByRoute;

缓存内容是否根据路由进行区分。 一个路由是由请求的控制器ID和动作ID组成的。 默认值是true。

varyBySession 属性
public boolean $varyBySession;

缓存内容是否根据用户会话进行区分。默认值是false。

方法详细

checkContentCache() 方法
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>&& ($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;
}

在缓存中查找内容。

filter() 方法
public boolean filter(CFilterChain $filterChain)
$filterChain CFilterChain 将被应用到动作的过滤器的列表
{return} boolean 在这个过滤器执行之后是否停止过滤处理。默认值是false。
public function filter($filterChain)
{
    if(!
$this->getIsContentCached())
        
$filterChain->run();
    
$this->run();
}

在动作被运行前执行过滤。 如果需要前置过滤,那么派生类应当覆盖此方法。

getBaseCacheKey() 方法
protected string getBaseCacheKey()
{return} string 没有变化的基本缓存键值。
protected function getBaseCacheKey()
{
    return 
self::CACHE_KEY_PREFIX.$this->getId().'.';
}

计算基本缓存键值。 计算出的键值在getCacheKey可以进一步变动。 派生类如果需要更多的变化,可以覆盖此方法。

getCache() 方法
protected ICache getCache()
{return} ICache 用于缓存内容的缓存器
protected function getCache()
{
    return 
Yii::app()->getComponent($this->cacheID);
}

getCacheKey() 方法
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, varyByParamvaryBySession

getIsContentCached() 方法
public boolean getIsContentCached()
{return} boolean 内容是否已在缓存中存在
public function getIsContentCached()
{
    if(
$this->_contentCached!==null)
        return 
$this->_contentCached;
    else
        return 
$this->_contentCached=$this->checkContentCache();
}

init() 方法
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()方法之前的内容 将被获取并保存在缓存中。 如果可用的内容在缓存中已存在则此方法什么也不会做。

recordAction() 方法
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);
}

当输出缓存有效时记录一个方法调用。 当内容是由输出缓存提供时,记录方法将被 重调用。

replayActions() 方法
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])));
    }
}

重做被记录的方法调用的集合。

run() 方法
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()方法之后的内容 将被获取并保存在缓存中。 如果可用的内容在缓存中已存在则此方法什么也不会做。