[译]Yii_Page_Caching

译文

1.输出缓存
2.HTTP缓存

页面缓存指的是将整个页面缓存住。页面缓存可以在不同的地方进行。例如,通过选取合适的HTTP头,客户端浏览器可以将浏览的页面在限定的时间内缓存住。web应用本身也可将页面存储在缓存中。

1.输出缓存(Output Caching)

页面缓存可以当作是片段缓存的特例。因为页面内容通常是由试图上应用布局来生成的,如果只是简单的在布局上调用beginCache()和endCache()是没有效果的。原因是,在视图被计算出来之后,再会在CController::render()方法中应用布局文件。

为了将整个页面缓存住,就要跳过action生成页面内容的代码。我们可以使用COutputCache作为action过滤器来完成这个任务。下面的代码显示了如何配置缓存过滤器:

1
2
3
4
5
6
7
8
9
10
public function filters()
{
return array(
array(
'COutputCache',
'duration' => 100,
'varyByParam' => array('id'),
),
);
}

上面的过滤器配置会应用到控制器中的所有方法上。我们可以使用加号操作符(+),限制它只发生在一个或几个方法上。更多的细节可以在控制器中找到。

Tip:COutputCache可以作为过滤器是因为它继续自CFileterWidget,而CFilterWidget既是过滤器又是挂件。事实上,挂件的运作方式跟过滤器是很像的:一个挂件(过滤器)会在任何内嵌的内容(方法)被计算之前开始运行,并且挂件(过滤器)会在任何内嵌的内容(方法)被计算之后结束。

2.HTTP缓存

作为简单的缓存方法输出内容的补充,Yii在1.1.11版本引入了CHttpCacheFilter。这个过滤器有助于设置前述的HTTP头来通知客户端在前次请求之后页面内容没有发生改变,这样,服务器不需要重新传输页面内容。CHttpCacheFilter的设置和COutputCache相似:

1
2
3
4
5
6
7
8
9
10
public function filter()
{
return array(
array(
'CHttpCacheFilter + index',
'lastModified' => Yii::app()->db->createCommand("SELECT MAX(update_time) FROM post")
->queryScalar(),
),
);
}

上面的代码将HTTP头的Last-Modified设置为文章最后修改的时间。你也可以使用CHttpCacheFilter::lastModifiedExpression(php表达式)来设置HTTP头的Last-Modified。

Tip:CHttpCacheFilter::lastModifiedExpression和CHttpCacheFilter::lastModified都能使用整数表示Unix时间戳或者任意的字符串表示可人识别的时间。后一种方式可以使用strtotime()解析,不许要其它转换。

SEO提示
搜索引擎机器人倾向于考虑缓存中的HTTP头信息。由于一些爬虫对单位时间内处理的一个域的页面数量有限制,引入缓存HTTP头或许有助于爬虫索引你的站点,因为这样做减少了爬虫处理的页面数量。

原文

Yii Page Caching

1
2
Output Caching
HTTP Caching

Page caching refers to caching the content of a whole page. Page caching can occur at different places. For example, by choosing an appropriate page header, the client browser may cache the page being viewed for a limited time. The Web application itself can also store the page content in cache.

  1. Output Caching

Page caching can be considered as a special case of fragment caching. Because the content of a page is often generated by applying a layout to a view, it will not work if we simply call beginCache() and endCache() in the layout. The reason is because the layout is applied within the CController::render() method AFTER the content view is evaluated.

To cache a whole page, we should skip the execution of the action generating the page content. We can use COutputCache as an action filter to accomplish this task. The following code shows how we configure the cache filter:

1
2
3
4
5
6
7
8
9
10
public function filters()
{
return array(
array(
'COutputCache',
'duration'=>100,
'varyByParam'=>array('id'),
),
);
}

The above filter configuration would make the filter to be applied to all actions in the controller. We may limit it to one or a few actions only by using the plus operator. More details can be found in filter.

Tip: We can use COutputCache as a filter because it extends from CFilterWidget, which means it is both a widget and a filter. In fact, the way a widget works is very similar to a filter: a widget (filter) begins before any enclosed content (action) is evaluated, and the widget (filter) ends after the enclosed content (action) is evaluated.
  1. HTTP Caching

In addition to simply caching the output of an action, Yii introduced CHttpCacheFilter in version 1.1.11. This filter aids in setting the aforementioned headers to notify a client that a page’s content has not been changed since the last request, so the server will not have to re-transmit the content. CHttpCacheFilter can be set up similar to COutputCache:

public function filters()
{

return array( array( 'CHttpCacheFilter + index', 'lastModified'=>Yii::app()->db->createCommand("SELECT MAX(update_time) FROM post")->queryScalar(), ), );

}

The above code will set the Last-Modified header to the last date at which a post was updated. You can also use CHttpCacheFilter::lastModifiedExpression to set the Last-Modified header using a php expression.

Tip: Both, CHttpCacheFilter::lastModifiedExpression and CHttpCacheFilter::lastModified can take either an integer representing an epochal Unix timestamp or an arbitrary string representing a human-readable date. As long as later one can be parsed by strtotime(), no further conversion is necessary.

The “Entity Tag” (or ETag for short) header can be set in a similar fashion through CHttpCacheFilter::etagSeed and CHttpCacheFilter::etagSeedExpression , respectively. Both will be serialized (so you can use either a single value or an entire array) and are used to generate a quoted, base64-encoded SHA1 hash serving as content for the ETag header. This differs from the way the Apache Webserver and others are generating their ETags. However, this method is perfectly in line with the RFC and turned out to be more feasible for use in a framework.

Note: In order to comply with RFC 2616, section 13.3.4, CHttpCacheFilter will send out ETag and Last-Modified headers if they can both be generated. Consequently, both will be used for cache validation if sent by the client.

Since entity tags are hashes, they allow more complex and/or more precise caching strategies than Last-Modified headers. For instance, an ETag can be invalidated if the site has switched to another theme.

Tip: Expensive expressions for CHttpCacheFilter::etagSeedExpression may defeat the purpose of CHttpCacheFilter and introduce unnecessary overhead, since they need to be re-evaluated on every request. Try to find a simple expression that invalidates the cache if the page content has been modified.

SEO Implications

Search engine bots tend to respect cache headers. Since some crawlers have a limit on how many pages per domain they process within a certain time span, introducing caching headers may help indexing your site as they reduce the number of pages that need to be processed.