
How to cache Magento collection query results
Table of Contents
Introduction
Today, I would like to introduce “How to cache the Magento collection result” without customizing the PHP code. When you have worked with the Magento collection, you would like to consider if you can cache the result for the next time if the data aren’t generally updated by admin or 3rd tools. By default, Magento support saves the result of the collection to cache but it is not enabled by default, we have to add some custom to di.xml to active the feature. And here are detailed steps.
I have an example for this case:
- I want to load a list of banners from the homepage, as you know the banner slider collection is not generally updated. Thus, I created a block that is used for getting banner collection
BannerSlider.php
<?php
/**
* Copyright © MagEx Digital All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace MagEx\BannerSlider\Block\Widget;
use Magento\Framework\View\Element\Template;
use Magento\Widget\Block\BlockInterface;
use MagEx\BannerSlider\Model\ResourceModel\Slider\CollectionFactory;
class BannerSlider extends Template implements BlockInterface
{
protected $_sliderCollectionFactory;
public function __construct(
Template\Context $context,
CollectionFactory $sliderCollectionFactory,
array $data = [])
{
parent::__construct($context, $data);
$this->_sliderCollectionFactory = $sliderCollectionFactory;
}
public function getSliderCollection(){
return $this->_sliderCollectionFactory->create();
}
}
Code language: HTML, XML (xml)
As you can see, I just have created a widget that loads the slider collection without implementing the cache, now I will introduce you to how to cache the $sliderCollection without modifying the class Widget\BannerSlider
Create a dependency injection file: di.xml
Absolutely, you have to create a di.xml file for updating the class constructor parameters. Creating a di.xml under module_folder/etc/di.xml with sample code below
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- Sample di.xml file -->
</config>
Code language: HTML, XML (xml)
The $fetchStrategy
As I mentioned above that Magento supports cache the result of collection by default, now you can check the $fetchStategy on \Magento\Framework\Data\Collection\AbstractDb (file: vendor/magento/framework/Data/Collection/AbstractDb.php).
CacheFetchStrategy
By default the interface FetchStrategyInterface is preferenced by Magento\Framework\Data\Collection\Db\FetchStrategy\Query, Therefore we have to update the Slider\Collection to use the CacheStrategy instead for activating the cache. I will add those line to the di.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagEx\BannerSlider\Model\ResourceModel\Slider\Collection">
<arguments>
<argument name="fetchStrategy" xsi:type="object">Magento\Framework\Data\Collection\Db\FetchStrategy\Cache</argument>
</arguments>
</type>
</config>
Code language: HTML, XML (xml)
The cache tags
Cleaning the cache, congratulation you have enabled the cache for Slider\Collection. But, what about if you want to clean the collection cache by tags? because the default stores the cache with the tag COLLECTION_DATA. If you want to adding some custom tags here is a sample
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="SliderCollectionCacheFetchStrategy" type="Magento\Framework\Data\Collection\Db\FetchStrategy\Cache">
<arguments>
<argument name="cacheTags" xsi:type="array">
<item name="slider" xsi:type="string">banner_slider_collection</item>
</argument>
</arguments>
</virtualType>
<type name="MagEx\BannerSlider\Model\ResourceModel\Slider\Collection">
<arguments>
<argument name="fetchStrategy" xsi:type="object">SliderCollectionCacheFetchStrategy</argument>
</arguments>
</type>
</config>
Code language: HTML, XML (xml)
Enable cache for special class
After all, you have enabled the cache for Banner\Slider\Collection but it enables global scope, every class that requires Banner\Slider\Collection will have cache and UiComponent is included. Absolutly, we don’t want to the UiComponent use the cache. Thus, we have to create a virual class for the collection. And here is a sample on enable caching for the Banner\Slider\Collection on BannerSlider. Updates the di.xml.
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="SliderCollectionCacheFetchStrategy" type="Magento\Framework\Data\Collection\Db\FetchStrategy\Cache">
<arguments>
<argument name="cacheTags" xsi:type="array">
<item name="slider" xsi:type="string">banner_slider_collection</item>
</argument>
</arguments>
</virtualType>
<virtualType name="VirtualBannerSliderCollection" type="MagEx\BannerSlider\Model\ResourceModel\Slider\Collection">
<arguments>
<argument name="fetchStrategy" xsi:type="object">SliderCollectionCacheFetchStrategy</argument>
</arguments>
</virtualType>
<virtualType name="VirtualTypeBannerSliderCollectionFactory" type="MagEx\BannerSlider\Model\ResourceModel\Slider\CollectionFactory">
<arguments>
<argument name="instanceName" xsi:type="string">VirtualBannerSliderCollection</argument>
</arguments>
</virtualType>
<type name="\MagEx\BannerSlider\Block\Widget\BannerSlider">
<arguments>
<argument name="sliderCollectionFactory" xsi:type="object">VirtualTypeBannerSliderCollectionFactory</argument>
</arguments>
</type>
</config>
Code language: HTML, XML (xml)
That’s all, you have enabled the cache for the Banner\Slider\Collection of the class Widget\BannerSlider thanks for reading my blog.
8 thoughts on “How to cache Magento collection query results”
Your lesson is very usefull. Thanks bro
My website was extremely slow until I read this article. Thank you so much
Amazing!!! you saved my life.
Amazing!!!! you saved my life.
This is great. Can I share your work with our top executives?
Thank brother :))
Great guide.
Thank you
Thank you so much! Your lesson is very useful for me!