3

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.

4

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.

|improve this answer|||||
  • Please would you be able to share how you did your plugin for block cache as mine is not working and I have a similar requirement as yours I need the block cache to be unique per customer – Goose84 Aug 5 '18 at 7:49
  • @Goose84 Edited the answer. Check now – Jay Ghosh Aug 5 '18 at 10:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.