Page 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:

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.

2. 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.

$Id$

Be the first person to leave a comment

Please to leave your comment.