View Model Cache Tags for Cache Invalidation
Hyvä enhances Magento's cache tag system, allowing view models to contribute page cache tags. This addresses a Magento limitation where view models couldn't invalidate pages when underlying data (e.g., product, category) changed. Hyvä automatically collects these view model cache tags and applies them to both Full Page Cache (FPC) and Block HTML cache records.
This guide explains how to implement cache tags in view models and how Hyvä's ViewModelRegistry collects them. Basic understanding of Magento Block HTML and Full Page Caching is recommended.
The Problem: View Models Lack Cache Tag Support
Hyvä themes heavily rely on View Models, accessed via the Hyvä ViewModelRegistry:
/** @var \Hyva\Theme\Model\ViewModelRegistry $viewModels */
$productPriceViewModel = $viewModels->require(\Hyva\Theme\ViewModel\ProductPrice::class);
Magento's core architecture doesn't allow view models to contribute cache tags to page responses. Consequently, pages using view models might not invalidate correctly when their underlying data changes.
Hyvä's Solution: Using IdentityInterface
Hyvä's ViewModelRegistry allows view models to contribute cache tags by implementing Magento\Framework\DataObject\IdentityInterface, mirroring how blocks provide FPC cache tags.
Example: Implementing Cache Tags in a View Model
This example demonstrates a view model returning the current product's cache tags. Pages using this view model will automatically invalidate when the product is modified:
class CurrentProduct implements
ArgumentInterface,
\Magento\Framework\DataObject\IdentityInterface
{
// ...
public function getIdentities(): array
{
// Delegate to the product's own cache tags if it implements IdentityInterface
return $this->currentProduct instanceof IdentityInterface
? $this->currentProduct->getIdentities()
: [];
}
}
Automatic Collection
When a template calls $viewModels->require(), the ViewModelRegistry checks if the view model implements IdentityInterface. If it does, the view model's getIdentities() return values are automatically added to the page response's X-Magento-Tags header (for FPC invalidation) and to Block HTML cache records.
Technical Implementation Details
Internal Documentation
The following content details Hyvä's internal implementation. While not required for using view model cache tags (simply implement IdentityInterface), it provides insight into how the system works.
How ViewModelRegistry Collects Cache Tags
When ViewModelRegistry::require() instantiates a view model, it calls Hyva\Theme\Model\ViewModelCacheTags::collectFrom($viewModel) to register any view models implementing IdentityInterface.
The ViewModelCacheTags class stores these view model references and provides a get() method to retrieve all collected cache tags.
Lazy Evaluation of getIdentities()
Cache tags are collected lazily; getIdentities() is called only when the response is finalized. This is crucial because some view models, like the Navigation view model, accumulate data and build their cache tags during rendering. Calling getIdentities() prematurely would omit categories loaded later.
Supported Cache Configurations
The view model cache tag system works correctly in all cache configurations:
- FPC only (Varnish or built-in)
- Block HTML cache only
- Both FPC and Block HTML cache enabled simultaneously
Adding Tags to Page Responses
For standard page requests, Hyvä injects Hyva\Theme\Block\ViewModelCacheTagsBlock into every page via the before.body.end container in the hyva_default layout handle.
This block, though rendering no visible output, implements IdentityInterface. When Magento collects block identities for the X-Magento-Tags response header, it calls getIdentities() on this block, which then returns all cache tags collected from view models during page rendering.
Debugging Cache Tags
In developer mode, ViewModelCacheTagsBlock renders an HTML comment listing all view model cache tags, useful for verifying correct cache tag propagation.
Adding Tags to ESI Responses
ESI (Edge Side Includes) requests require special handling, as content might be served from Block HTML cache without view model instantiation.
ESI Without Block HTML Cache
When ESI content is not also Block HTML cached, cache tags are added normally: view models are instantiated, and their tags are collected and added to ESI response headers.
ESI with Block HTML Cache (Double-Cached Blocks)
For content cached in both ESI and Block HTML cache (e.g., navigation menu), the Block HTML cache serves the response directly, bypassing view model instantiation. This would typically exclude view model cache tags from the ESI response.
Hyvä addresses this with a two-part mechanism:
- Tag Storage: A plugin on
Layout::getOutput()identifies blocks cached in both ESI and Block HTML cache, storing their view model cache tags in a separate Block HTML cache record. - Tag Retrieval: The plugin
Hyva\Theme\Plugin\PageCache\AddViewModelCacheTagesToEsiResponseonMagento\PageCache\Controller\Block\Esiretrieves these stored tags and adds them to the ESI response'sX-Magento-Tagsheader.
This ensures correct cache invalidation even when ESI content is served from Block HTML cache.