mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-10-31 10:39:59 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			185 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			7.3 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.
 | |
| 
 | |
| To delete fragment caching you can use
 | |
| ```php
 | |
| Yii::$app->cache->delete(['yii\widgets\FragmentCache', $id]);
 | |
| ```
 | |
| 
 | |
| 
 | |
| ## Caching Options <span id="caching-options"></span>
 | |
| 
 | |
| 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 <span id="duration"></span>
 | |
| 
 | |
| 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 60, which means the cached content will expire in 60 seconds.
 | |
| 
 | |
| 
 | |
| ### Dependencies <span id="dependencies"></span>
 | |
| 
 | |
| 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 <span id="variations"></span>
 | |
| 
 | |
| 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 <span id="toggling-caching"></span>
 | |
| 
 | |
| 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 <span id="nested-caching"></span>
 | |
| 
 | |
| 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 <span id="dynamic-content"></span>
 | |
| 
 | |
| 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.
 | |
| 
 | |
| > Note: since version 2.0.14 a dynamic content API is exposed via the [[yii\base\DynamicContentAwareInterface]] interface and its [[yii\base\DynamicContentAwareTrait]] trait.
 | |
|   As an example, you may refer to the [[yii\widgets\FragmentCache]] class.
 | 
