5

I have filter catalog product collection based customer logged in frontend, Using event observer catalog_block_product_list_collection, Filter working fine. But the issue is found in Layered navigation and pagination count and won't be update or changes count based on filter applied.

Can anyone help me how can I resolved and what changes need to done further. enter image description here

3

Try it.

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        //Current customer id
        $customerSession = $objectManager->create('\Magento\Customer\Model\Session');
        $cid = $customerSession->getCustomer()->getId();

        $productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\Collection');

        $productCollection->addAttributeToSelect('*');
        $productCollection->addAttributeToFilter(
                array(
                    array('attribute'=>'allowed_customers', 'like'=>$cid.',%'),
                    array('attribute'=>'allowed_customers', 'like'=>'%,'.$cid.',%'),
                    array('attribute'=>'allowed_customers', 'like'=>'%,'.$cid),
                    array('attribute'=>'allowed_customers', 'like'=>'%'.$cid),
                    array('attribute'=>'allowed_customers', 'like'=>'%'.$cid.'%'),
                    array('attribute'=>'allowed_customers', 'like'=>$cid.'%')));

        $productCollection->load();

        $skus = $productCollection->getColumnValues('sku');
        $skus = array_unique($skus);

        //$skus = array('24-MB04', '24-MB03', '24-MB02');

        $this->filterBuilder->setField('sku');
        $this->filterBuilder->setValue($skus);
        $this->filterBuilder->setConditionType('in');

        $this->searchCriteriaBuilder->addFilter($this->filterBuilder->create());
  • this solution will fail due to array('attribute'=>'allowed_customers', 'like'=>'%'.$cid), array('attribute'=>'allowed_customers', 'like'=>'%'.$cid.'%'), array('attribute'=>'allowed_customers', 'like'=>$cid.'%') these three conditions. for example if $cid=2 then it will load data for all customers having id 2 or 22 or 222 and continue. Please think and correct – Nalin Savaliya Jun 23 '17 at 12:33
3

Please follow this solution

You need to create your list of SKUs as below and then apply it as explained in above answer

//------------------- Custom Filter ----------------[START]
            $objectManager = \Magento\Framework\App\ObjectManager::getInstance();

            //Current customer id
            $customerSession = $objectManager->create('\Magento\Customer\Model\Session');
            $cid = $customerSession->getCustomer()->getId();

            //create your product collection and apply your custom field filterBuilder
            $productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\Collection');
            /** Apply filters here */

            $productCollection->addAttributeToSelect('*');
            $productCollection->addAttributeToFilter('allowed_customer', array('like' => $cid.',%'));
            $productCollection->addAttributeToFilter('allowed_customer', array('like' => '%,'.$cid.',%'));
            $productCollection->addAttributeToFilter('allowed_customer', array('like' => '%,'.$cid));
            $productCollection->load();

            $skus = $productCollection->getColumnValues('sku');
            $skus = array_unique($skus);

            //$skus = array('24-MB04', '24-MB03', '24-MB02');

            $this->filterBuilder->setField('sku');
            $this->filterBuilder->setValue($skus);
            $this->filterBuilder->setConditionType('in');

            $this->searchCriteriaBuilder->addFilter($this->filterBuilder->create());

        //------------------- Custom Filter ----------------[END]

Please give a try, I have not tested

1

Ran into a while back. The problem we observed was the collection item count and toolbar page counts were being set before the collection was being modified.

Vendor/Module/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
  <type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
    <plugin name="vendor_module_plugin_toolbar" type="Vendor\Module\Plugin\Toolbar" sortOrder="1" disabled="false"/>
  </type>
  <type name="Magento\Framework\Data\Collection">
    <plugin name="vendor_module_plugin_collection" type="Vendor\Module\Plugin\Toolbar" sortOrder="1" disabled="false"/>
  </type>
</config>

There are two import notes about the code below:

  1. The plugin only updates totals and pagination when a navigation filter is active, because we were only modifying collections with an active filter. If you want the plugin to run against all collections remove the conditional statements referencing $this->isFilterActive().
  2. You need to know the class name of the collections you are targeting and add them to the $targets array in function isTargetCollection. Without this the plugin would potentially alter the result of getTotalNum on all collections. I'm really not a fan of the plugin on Magento\Framework\Data\Collection and it would be advisable to search out a cleaner method of updating the collection totals.

Vendor/Module/Plugin/Toolbar.php

<?php
namespace Vendor\Module\Plugin;

use Magento\Catalog\Model\Layer\Resolver;

class Toolbar {
    protected $layer;

    public function __construct(
        Resolver $layerResolver
    ) {
        $this->layer = $layerResolver->get();
    }

    public function afterGetTotalNum($subject, $result) {
        if($this->isFilterActive()){
            return $result;
        }

        $totalRecords = $this->getTotalNum($subject->getCollection());

        return intval($totalRecords);
    }

    public function afterGetLastPageNumber($subject, $result) {
        if($this->isFilterActive() || !$this->isTargetCollection($subject)){
            return $result;
        }

        $totalRecords = intval($this->getTotalNum($subject));
        $pageSize = $subject->getPageSize();
        $lastPage = ceil($totalRecords/$pageSize);

        return $lastPage;
    }

    private function getTotalNum($collection) {
        $sql = $collection->getSelectCountSql();
        return $collection->getConnection()->fetchOne($sql, []);
    }

    private function isFilterActive() {
        $filterCount = count($this->layer->getState()->getFilters());
        return ($filterCount ? true : false);
    }

    private function isTargetCollection($subject) {
        $targets = array(
            'Magento\CatalogStaging\Model\ResourceModel\Fulltext\Collection\Interceptor'
        );
        if (in_array(get_class($subject), $targets)) {
            return true;
        }
        return false;
    }
}
  • I have tried implemented plugin as you suggest and You can see item count shows perfect, But still pagination and layered navigation count seems incorrect. – Prashant Gohil Jun 13 '17 at 12:53

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.