array( ...... 'components'=>array( ...... 'cache'=>array(
'class'=>'system.caching.CMemCache', 'servers'=>array(
array('host'=>'server1', 'port'=>11211, 'weight'=>60), array('host'=>'server2', 'port'=>11211, 'weight'=>40), ), ), ), );
Yii::app()->cache
访问。
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 版开始支持。
// 值$value 在缓存中最多保留30秒Yii::app()->cache->set($id, $value, 30);
// 此值将在30秒后失效// 也可能因依赖的文件发生了变化而更快失效Yii::app()->cache->set($id, $value, 30, new CFileCacheDependency('FileName'));
$value
,依赖关系将被检查,如果发生改变,我们将会得到一个 false 值,表示数据需要被重新生成。
如下是可用的缓存依赖的简要说明:
CFileCacheDependency: 如果文件的最后修改时间发生改变,则依赖改变。
CDirectoryCacheDependency: 如果目录和其子目录中的文件发生改变,则依赖改变。
CDbCacheDependency: 如果指定 SQL 语句的查询结果发生改变,则依赖改变。
CGlobalStateCacheDependency: 如果指定的全局状态发生改变,则依赖改变。全局状态是应用中的一个跨请求,跨会话的变量。它是通过 CApplication::setGlobalState() 定义的。
CChainedCacheDependency: 如果链中的任何依赖发生改变,则此依赖改变。
CExpressionDependency: 如果指定的 PHP 表达式的结果发生改变,则依赖改变。此类从版本 1.0.4 起可用。
...别的HTML内容... <?php if($this->beginCache($id)) { ?> ...被缓存的内容... <?php $this->endCache(); } ?> ...别的HTML内容...
if
语句内的内容将被执行并在 endCache()
触发时缓存。
也许是最常见的选项是duration,指定了内容在缓存中多久有效。和CCache::set()过期参数有点类似。下面的代码缓存内容片段最多一小时:
...其他HTML内容... <?php if($this->beginCache($id, array('duration'=>3600))) { ?> ...被缓存的内容... <?php $this->endCache(); } ?> ...其他HTML内容...
像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内容...
COutputCache内置了这一特征,程序员不需要编写根据ID变动内容的模式。以下是摘要。
varyByRoute: 设置此选项为true ,缓存的内容将根据route变化。因此,每个控制器和行动的组合将有一个单独的缓存内容。
varyBySession: 设置此选项为true ,缓存的内容将根据session ID变化。因此,每个用户会话可能会看到由缓存提供的不同内容。
varyByParam: 设置此选项的数组里的名字,缓存的内容将根据GET参数的值变动。例如,如果一个页面显示文章的内容根据id
的GET参数,我们可以指定varyByParam为array('id')
,以使我们能够缓存每篇文章内容。如果没有这样的变化,我们只能能够缓存某一文章。
varyByExpression: by setting this option to a PHP expression, we can make the cached content to be variated according to the result of this PHP expression. This option has been available since version 1.0.4.
有时候,我们希望片段缓存只对某些类型的请求启用。例如,对于某张网页上显示表单,我们只想要缓存initially requested表单(通过GET请求)。任何随后显示(通过POST请求)的表单将不被缓存,因为表单可能包含用户输入。要做到这一点,我们可以指定requestTypes 选项:
...其他HTML内容... <?php if($this->beginCache($id, array('requestTypes'=>array('GET')))) { ?> ...被缓存的内容... <?php $this->endCache(); } ?> ...其他HTML内容...
片段缓存可以嵌套。就是说一个缓存片段附在一个更大的片段缓存里。例如,意见缓存在内部片段缓存,而且它们一起在外部缓存中在文章内容里缓存。
...其他HTML内容... <?php if($this->beginCache($id1)) { ?> ...外部被缓存内容... <?php if($this->beginCache($id2)) { ?> ...内部被缓存内容... <?php $this->endCache(); } ?> ...外部被缓存内容... <?php $this->endCache(); } ?> ...其他HTML内容...
嵌套缓存可以设定不同的缓存选项。例如, 在上面的例子中内部缓存和外部缓存可以设置时间长短不同的持续值。当数据存储在外部缓存无效,内部缓存仍然可以提供有效的内部片段。 然而,反之就不行了。如果外部缓存包含有效的数据, 它会永远保持缓存副本,即使内容中的内部缓存已经过期。
如果想要缓存整个页面,我们应该跳过产生网页内容的动作执行。我们可以使用COutputCache作为动作 过滤器来完成这一任务。下面的代码演示如何配置缓存过滤器:
public function filters(){
return array(
array(
'COutputCache', 'duration'=>100, 'varyByParam'=>array('id'), ), ); }
上述过滤器配置会使过滤器适用于控制器中的所有行动。 我们可能会限制它在一个或几个行动通过使用插件操作器。 更多的细节中可以看过滤器。
当使用fragment caching或page caching,我们常常遇到的这样的情况 整个部分的输出除了个别地方都是静态的。例如,帮助页可能会显示静态的帮助 信息,而用户名称显示的是当前用户的。
解决这个问题,我们可以根据用户名匹配缓存内容,但是这将是我们宝贵空间一个巨大的浪费,因为缓存除了用户名其他大部分内容是相同的。我们还可以把网页切成几个片段并分别缓存,但这种情况会使页面和代码变得非常复杂。更好的方法是使用由 CController 提供的动态内容dynamic content功能 。
动态内容是指片段输出即使是在片段缓存包括的内容中也不会被缓存。即使是包括的内容是从缓存中取出,为了使动态内容在所有时间是动态的,每次都得重新生成。出于这个原因,我们要求 动态内容通过一些方法或函数生成。
调用CController::renderDynamic()在你想的地方插入动态内容。
...别的HTML内容... <?php if($this->beginCache($id)) { ?> ...被缓存的片段内容... <?php $this->renderDynamic($callback); ?> ...被缓存的片段内容... <?php $this->endCache(); } ?> ...别的HTML内容...
在上面的, $callback
指的是有效的PHP回调。它可以是指向当前控制器类的方法或者全局函数的字符串名。它也可以是一个数组名指向一个类的方法。其他任何的参数,将传递到renderDynamic()方法中。回调将返回动态内容而不是仅仅显示它。