Magento2 – Fix Collection Filter Issue with Cache Enabled

magento2

$myattr = $this->catalogSession->getData('myattribute');
if(!empty($myattr)){
    $collection = $this->_catalogLayer->getProductCollection();
    $attribute = $this->eavConfig->getAttribute('catalog_product', 'myattribute');
    $option_id = $attribute->getSource()->getOptionId($myattr);
    $collection->addAttributeToFilter('myattribute',array('finset'=>$option_id));
}

in Block/Category/MyattributeChooser.php in the _prepareLayout function

This works if I have caching disabled OR I select any filter at all. It does not work if caching is enabled but I used my custom chooser and no other filters are displayed.

I need to know how to make it work. This is on a categories page. I could just totally turn off caching for the chooser but that isn't a very good answer.

I've found too that although it works it doesn't recalculate pagination either. $collection->getSize() results in an Illegal State error and $collection->clear() and $collection->resetData() have no effect on anything whatsoever. $collection->isLoaded() returns NULL.

Best Answer

In MyCompany/MyModule/etc/di.xml:

<?xml version="1.0"?>
<!--
/**
 * @copyright Copyright (c) 2016 https://chillydraji.wordpress.com
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Model\ResourceModel\Product\Collection">
        <plugin name="AddFilter" type="MyCompany\MyModule\Model\Plugin\AddFilter"/>
    </type>
</config>

In MyCompany/MyModule/Model/Plugin/AddFilter.php

<?php namespace MyCompany\MyModule\Model\Plugin;

use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;

class AddFilter
{
    /**
     * aroundAddFieldToFilter method
     *
     * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
     * @param \Closure                                                $proceed
     * @param                                                         $fields
     * @param null                                                    $condition
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    public function aroundAddFieldToFilter(ProductCollection $collection, \Closure $proceed, $fields, $condition = null)
    {
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $eavConfig = $objectManager->create('\Magento\Eav\Model\Config');
        $session = $objectManager->create('\Magento\Catalog\Model\Session');
        $attribute = $eavConfig->getAttribute('catalog_product', 'carfilter');
        $car_attr = $session->getData('car_attr');
        if(!empty($car_attr)){
            $option_id = $attribute->getSource()->getOptionId($car_attr);
            $collection->addAttributeToFilter('carfilter',array('finset'=>$option_id));
        }

        return $fields ? $proceed($fields, $condition) : $collection;
    }
}

Info on how to do the di.xml and class taken from here: Magento2 - How to filter product collection on category view

However, it still is really esoteric and I don't like it but it works and no one answered me.

Additionally, for filters to work with cache being enabled you have to utilize adding the filter value to the URL as a GET string, or fetch such a page with AJAX, this is how the layered navigation does it.

Related Topic