mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 06:37:55 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			177 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
Fragment Caching
 | 
						|
================
 | 
						|
 | 
						|
Fragment caching refers to caching a fragment of a Web page. For example, if a page displays a summary of
 | 
						|
yearly sale in a table, you can store this table in cache to eliminate the time needed to generate this table
 | 
						|
for each request. Fragment caching is built on top of [data caching](caching-data.md).
 | 
						|
 | 
						|
To use fragment caching, use the following construct in a [view](structure-views.md):
 | 
						|
 | 
						|
```php
 | 
						|
if ($this->beginCache($id)) {
 | 
						|
 | 
						|
    // ... generate content here ...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
That is, enclose content generation logic in a pair of [[yii\base\View::beginCache()|beginCache()]] and
 | 
						|
[[yii\base\View::endCache()|endCache()]] calls. If the content is found in the cache, [[yii\base\View::beginCache()|beginCache()]]
 | 
						|
will render the cached content and return false, thus skip the content generation logic.
 | 
						|
Otherwise, your content generation logic will be called, and when [[yii\base\View::endCache()|endCache()]]
 | 
						|
is called, the generated content will be captured and stored in the cache.
 | 
						|
 | 
						|
Like [data caching](caching-data.md), a unique `$id` is needed to identify a content cache.
 | 
						|
 | 
						|
 | 
						|
## Caching Options <a name="caching-options"></a>
 | 
						|
 | 
						|
You may specify additional options about fragment caching by passing the option array as the second
 | 
						|
parameter to the [[yii\base\View::beginCache()|beginCache()]] method. Behind the scene, this option array
 | 
						|
will be used to configure a [[yii\widgets\FragmentCache]] widget which implements the actual fragment caching
 | 
						|
functionality.
 | 
						|
 | 
						|
### Duration <a name="duration"></a>
 | 
						|
 | 
						|
Perhaps the most commonly used option of fragment caching is [[yii\widgets\FragmentCache::duration|duration]].
 | 
						|
It specifies for how many seconds the content can remain valid in a cache. The following code
 | 
						|
caches the content fragment for at most one hour:
 | 
						|
 | 
						|
```php
 | 
						|
if ($this->beginCache($id, ['duration' => 3600])) {
 | 
						|
 | 
						|
    // ... generate content here ...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
If the option is not set, it will take the default value 0, which means the cached content will never expire.
 | 
						|
 | 
						|
 | 
						|
### Dependencies <a name="dependencies"></a>
 | 
						|
 | 
						|
Like [data caching](caching-data.md#cache-dependencies), content fragment being cached can also have dependencies.
 | 
						|
For example, the content of a post being displayed depends on whether or not the post is modified.
 | 
						|
 | 
						|
To specify a dependency, set the [[yii\widgets\FragmentCache::dependency|dependency]] option, which can be
 | 
						|
either an [[yii\caching\Dependency]] object or a configuration array for creating a dependency object. The
 | 
						|
following code specifies that the fragment content depends on the change of the `updated_at` column value:
 | 
						|
 | 
						|
```php
 | 
						|
$dependency = [
 | 
						|
    'class' => 'yii\caching\DbDependency',
 | 
						|
    'sql' => 'SELECT MAX(updated_at) FROM post',
 | 
						|
];
 | 
						|
 | 
						|
if ($this->beginCache($id, ['dependency' => $dependency])) {
 | 
						|
 | 
						|
    // ... generate content here ...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
### Variations <a name="variations"></a>
 | 
						|
 | 
						|
Content being cached may be variated according to some parameters. For example, for a Web application
 | 
						|
supporting multiple languages, the same piece of view code may generate the content in different languages.
 | 
						|
Therefore, you may want to make the cached content variated according to the current application language.
 | 
						|
 | 
						|
To specify cache variations, set the [[yii\widgets\FragmentCache::variations|variations]] option, which
 | 
						|
should be an array of scalar values, each representing a particular variation factor. For example,
 | 
						|
to make the cached content variated by the language, you may use the following code:
 | 
						|
 | 
						|
```php
 | 
						|
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {
 | 
						|
 | 
						|
    // ... generate content here ...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
### Toggling Caching <a name="toggling-caching"></a>
 | 
						|
 | 
						|
Sometimes you may want to enable fragment caching only when certain conditions are met. For example, for a page
 | 
						|
displaying a form, you only want to cache the form when it is initially requested (via GET request). Any
 | 
						|
subsequent display (via POST request) of the form should not be cached because the form may contain user input.
 | 
						|
To do so, you may set the [[yii\widgets\FragmentCache::enabled|enabled]] option, like the following:
 | 
						|
 | 
						|
```php
 | 
						|
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
 | 
						|
 | 
						|
    // ... generate content here ...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
 | 
						|
## Nested Caching <a name="nested-caching"></a>
 | 
						|
 | 
						|
Fragment caching can be nested. That is, a cached fragment can be enclosed within another fragment which is also cached.
 | 
						|
For example, the comments are cached in an inner fragment cache, and they are cached together with the
 | 
						|
post content in an outer fragment cache. The following code shows how two fragment caches can be nested:
 | 
						|
 | 
						|
```php
 | 
						|
if ($this->beginCache($id1)) {
 | 
						|
 | 
						|
    // ...content generation logic...
 | 
						|
 | 
						|
    if ($this->beginCache($id2, $options2)) {
 | 
						|
 | 
						|
        // ...content generation logic...
 | 
						|
 | 
						|
        $this->endCache();
 | 
						|
    }
 | 
						|
 | 
						|
    // ...content generation logic...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Different caching options can be set for the nested caches. For example, the inner caches and the outer caches
 | 
						|
can use different cache duration values. Even when the data cached in the outer cache is invalidated, the inner
 | 
						|
cache may still provide the valid inner fragment. However, it is not true vice versa. If the outer cache is
 | 
						|
evaluated to be valid, it will continue to provide the same cached copy even after the content in the
 | 
						|
inner cache has been invalidated. Therefore, you must be careful in setting the durations or the dependencies
 | 
						|
of the nested caches, otherwise the outdated inner fragments may be kept in the outer fragment.
 | 
						|
 | 
						|
 | 
						|
## Dynamic Content <a name="dynamic-content"></a>
 | 
						|
 | 
						|
When using fragment caching, you may encounter the situation where a large fragment of content is relatively
 | 
						|
static except at one or a few places. For example, a page header may display the main menu bar together with
 | 
						|
the name of the current user. Another problem is that the content being cached may contain PHP code that
 | 
						|
must be executed for every request (e.g. the code for registering an asset bundle). Both problems can be solved
 | 
						|
by the so-called *dynamic content* feature.
 | 
						|
 | 
						|
A dynamic content means a fragment of output that should not be cached even if it is enclosed within
 | 
						|
a fragment cache. To make the content dynamic all the time, it has to be generated by executing some PHP code
 | 
						|
for every request, even if the enclosing content is being served from cache.
 | 
						|
 | 
						|
You may call [[yii\base\View::renderDynamic()]] within a cached fragment to insert dynamic content
 | 
						|
at the desired place, like the following,
 | 
						|
 | 
						|
```php
 | 
						|
if ($this->beginCache($id1)) {
 | 
						|
 | 
						|
    // ...content generation logic...
 | 
						|
 | 
						|
    echo $this->renderDynamic('return Yii::$app->user->identity->name;');
 | 
						|
 | 
						|
    // ...content generation logic...
 | 
						|
 | 
						|
    $this->endCache();
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
The [[yii\base\View::renderDynamic()|renderDynamic()]] method takes a piece of PHP code as its parameter.
 | 
						|
The return value of the PHP code is treated as the dynamic content. The same PHP code will be executed
 | 
						|
for every request, no matter the enclosing fragment is being served from cached or not.
 |