Cache
Displayer cache (Pro)
Displayers are cached with the service DisplayerCacheService
.
The caching parameters are controlled by the content block caching strategy. That strategy can define duration and different caching keys depending on user authentication, url and others.
Cache is enabled by default when devMode is disabled, this be changed by creating the config/themes.php
file :
<?php return [ 'displayerCache' => false ];
Displayer caching use Craft internal caching dependencies, saving an entry for example will clear all the displayer caches that use this entry.
If something changes in your code (templates, theme preferences
class, render events) and you're pushing to a production environment,
clear the caches : craft invalidate-tags/themes::displayers
.
Field displayers are cached in the template fields/_field
with the
token {% fielddisplayercache %}
, if you override a field template that
does not extend this template, you would need to add that token or
caching will be skipped.
Same idea for file displayers which use the token {% filedisplayercache %}
.
Each displayer method beforeRender()
will be called, even for
cached displayers, that can be used if you need to register asset
bundles or other things.
The cache can be disabled at field or displayer level by overriding
the FieldInterface::getCanBeCached(): bool
method. Cache is currently
disabled on :
- MatrixField : Cache happens at the Matrix level
- TableField : Cache happens at the Table level
- FileFile and AssetRenderFile : Cache happens at file displayer level
Generally, any displayer that handle Assets (file displayers) should
have its cache disabled, it's the file displayer themselves who should
be responsible for caching. Caching such a field displayer will result
in the beforeRender
of file displayers to not be called.
Rules cache
Theme resolution rules will be cached by default on environments
where devMode is disabled, this can be changed by creating the config/themes.php
file :
<?php return [ 'rulesCache' => false ];
If you change rules and deploy to a production environment, clear the cache : craft invalidate-tags/themes::rules
.
Template cache (Pro)
Template resolution will be cached by default on environments where
devMode is disabled, this can be changed by creating the config/themes.php
file :
<?php return [ 'templateCache' => false ];
If you create new templates and deploy to a production environment,
clear the cache : craft invalidate-tags/themes::templates
Block cache (Pro)
Block cache will be enabled by default on environments where devMode
is disabled, this can be changed by creating the config/themes.php
file :
<?php return [ 'blockCache' => false ];
Add a new strategy
Each block can have a cache strategy that defines how it will be cached.
Add a new strategy class :
<?php use Ryssbowh\CraftThemes\Themes; use Ryssbowh\CraftThemes\base\BlockCacheStrategy; use Ryssbowh\CraftThemes\interfaces\BlockInterface; use Ryssbowh\CraftThemes\models\BlockStrategyOptions; class MyCacheStrategy extends BlockCacheStrategy { const CACHE_TAG = 'themes.blockCache.myStrategy'; /** * @inheritDoc */ public function getHandle(): string { return 'my-strategy'; } /** * @inheritDoc */ public function getName(): string { return \Craft::t('themes', 'My strategy'); } /** * @inheritDoc */ public function getDescription(): string { return \Craft::t('themes', 'Block will be cached differently'); } /** * @inheritDoc */ public function getDuration(): ?int { return $this->options->duration * 60; } /** * @inheritDoc */ public function buildKey(BlockInterface $block): array { $key = [self::CACHE_TAG]; if ($this->options->cachePerAuthenticated) { $key[] = \Craft::$app->user ? 'auth' : 'noauth'; } if ($this->options->cachePerUser and $user = \Craft::$app->user) { $key[] = 'user-id-' . $user->getIdentity()->id; } if ($this->options->cachePerSite) { $site = \Craft::$app->sites->getCurrentSite(); $key[] = 'site-' . $site->id; } return $key; } /** * @inheritDoc */ protected function getOptionsModel(): string { return MyCacheStrategyOptions::class; } }
And an option class :
<?php use Ryssbowh\CraftThemes\models\BlockStrategyOptions; class MyCacheStrategyOptions extends BlockStrategyOptions { /** * @inheritDoc */ public function defineOptions(): array { return [ 'duration' => [ 'field' => 'text', 'type' => 'number', 'min' => 0, 'step' => 10, 'label' => \Craft::t('themes', 'Cache duration (minutes)'), 'instructions' => \Craft::t('themes', '0 means forever'), 'size' => 5 ], 'cachePerSite' => [ 'field' => 'lightswitch', 'label' => \Craft::t('themes', 'Cache depends on site') ], 'cachePerAuthenticated' => [ 'field' => 'lightswitch', 'label' => \Craft::t('themes', 'Cache depends on user authentication') ], 'cachePerUser' => [ 'field' => 'lightswitch', 'label' => \Craft::t('themes', 'Cache depends on user') ] ]; } /** * @inheritDoc */ public function defineDefaultValues(): array { return [ 'cachePerSite' => true, 'cachePerAuthenticated' => false, 'cachePerUser' => false, 'duration' => 0 ]; } /** * @inheritDoc */ public function defineRules(): array { return [ [['cachePerAuthenticated', 'cachePerUser', 'cachePerSite'], 'boolean', 'trueValue' => true, 'falseValue' => false], ['duration', 'integer'], ['duration', 'required'] ]; } }
And register it by responding to the event :
Event::on( BlockCacheService::class, BlockCacheService::REGISTER_STRATEGIES, function (RegisterBlockCacheStrategies $event) { $event->add(new MyCacheStrategy); });
Strategy classes must implement BlockCacheStrategyInterface
and
their options extend BlockStrategyOptions
which is a configurable
options class (but is not modifiable through
events).
Each block can disable caching entirely by overriding the method getCanBeCached(): bool
. The content block is non cacheable, but still
has a caching strategy which will define displayers caching.
Block cache can be cleared with the following command : craft invalidate-tags/themes::blocks