Domanda

I am currently working on an architecture where I'd like to maintain separate caches (block cache, collection cache, FPC) for each zipcode. I am making the user select a zipcode at the beginning of the journey, and I wrote plugins/observers for modifying various parts of Magento altogether (like fetching product price, which is different for each zipcode).

Everything seems to be working fine when I have cache disabled. But as I enable the cache, the data is cached for the first user and his/her zipcode, and it shows the same data to all users.

Now what I want is to maintain separate cache copies for each zipcode. I know that Magento keeps a separate cache copy for each store view. I did a lot of digging but couldn't find how Magento manages to do it. If someone could guide me to the classes/function which are responsible for the "store-view-based caching", then I could probably write plugins for those functions to maintain a zipcode based caching system.

È stato utile?

Soluzione

I finally solved it by writing a plugin for the Magento\Framework\App\PageCache\Identifier class

app/code/Vendor/Module/etc/frontend/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="Magento\Framework\App\PageCache\Identifier">
        <plugin name="append_zipcode_to_page_cache_identifier" type="Vendor\Module\Plugin\App\PageCache\Identifier"/>
    </type>
</config>

And the plugin class, app/code/Vendor/Module/Plugin/App/PageCache/Indentifier.php

<?php

namespace Vendor\Module\Plugin\App\PageCache;

use Magento\Framework\App\Http\Context;
use Magento\Framework\App\PageCache\Identifier as Subject;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Serialize\Serializer\Json;

class Identifier
{

    /**
     * @var Http
     */
    private $request;

    /**
     * @var Context
     */
    private $context;

    /**
     * @var Json
     */
    private $serializer;

    /**
     * Identifier constructor.
     * @param Http $request
     * @param Context $context
     * @param Json $serializer
     */
    public function __construct(
        Http $request,
        Context $context,
        Json $serializer
    )
    {
        $this->request = $request;
        $this->context = $context;
        $this->serializer = $serializer;
    }

    /**
     * @param Subject $subject
     * @param string $identifier
     * @return string
     */
    public function aroundGetValue(Subject $subject, $identifier) {
        $data = [
            $this->request->isSecure(),
            $this->request->getUriString(),
            $this->request->get(\Magento\Framework\App\Response\Http::COOKIE_VARY_STRING)
            ?: $this->context->getVaryString(),
            $this->getZipcode() // append zipcode to cache identifier
        ];
        return sha1($this->serializer->serialize($data));

    }

    protected function getZipcode() {
        return "123456"; // send the actual zipcode here
    }
}

For modifying the Block Cache and Model Cache, we can write an after plugin for the Magento\Framework\DataObject\IdentityInterface::getIdentities() method

Like So,

app/code/Vendor/Module/etc/frontend/di.xml

<type name="Magento\Framework\DataObject\IdentityInterface">
    <plugin name="block_and_model_cache_modification" type="Vendor\Module\Plugin\Identity" />
</type>

app/code/Vendor/Module/Plugin/Identity.php

<?php

namespace Vendor\Module\Plugin;

use Magento\Framework\DataObject\IdentityInterface as Subject;

class Identity
{
    /**
     * @param Subject $subject
     * @param array $identities
     * @return array
     */
    public function afterGetIdentities(Subject $subject, $identities) 
    {
        $identities[] = "My custom identity"; // append whatever identity you want your cache based on
        return $identities;
    }
}

Hope that helps.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a magento.stackexchange
scroll top