0

I want to filter product collection based on custom attribute on product listing page.

So I have to override _getProductCollection function from \vendor\magento\module-catalog\Block\Product\ListProduct.php in my customm module.

Below is my code:

 protected function _getProductCollection()
 {
    if ($this->_productCollection === null) {
        $layer = $this->getLayer();

        /* @var $layer \Magento\Catalog\Model\Layer */
        if ($this->getShowRootCategory()) {
            $this->setCategoryId($this->_storeManager->getStore()->getRootCategoryId());
        }

        // if this is a product view page
        if ($this->_coreRegistry->registry('product')) {
            // get collection of categories this product is associated with
            $categories = $this->_coreRegistry->registry('product')
                ->getCategoryCollection()->setPage(1, 1)
                ->load();
            // if the product is associated with any category
            if ($categories->count()) {
                // show products from this category
                $this->setCategoryId(current($categories->getIterator()));
            }
        }

        $origCategory = null;
        if ($this->getCategoryId()) {
            try {
                $category = $this->categoryRepository->get($this->getCategoryId());
            } catch (NoSuchEntityException $e) {
                $category = null;
            }

            if ($category) {
                $origCategory = $layer->getCurrentCategory();
                $layer->setCurrentCategory($category);
            }
        }
        $this->_productCollection = $layer->getProductCollection()->addAttributeToFilter('my_attribute_name', array('neq' => NULL));



        $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

        if ($origCategory) {
            $layer->setCurrentCategory($origCategory);
        }
    }

    return $this->_productCollection;
}

using this my filtered product shown in front side but it give wrong product count.

can any one help me?

2 Answers 2

1

It's a Magento default bug, Issue is solved here.

Fixing issue with getSize function not recalculating after adding filters.

Replace getSize() function code by below code

public function getSize()
    {
        $itemCount = count($this->_items);
        if ($this->_totalRecords === null || ($itemCount > 0 && $itemCount !== $this->_totalRecords)) {
            $sql = $this->getSelectCountSql();
            $this->_totalRecords = (int) $this->getConnection()->fetchOne($sql, $this->_bindParams);
        }
        return (int) $this->_totalRecords;
    }

You can fix it by apply given changes to your core file.

Core file Path : vendor/magento/framework/Data/Collection/AbstractDb.php

Note: This is a temporary solution.

3
  • @ suresh Chikani: can you please provide me core full path in magento 2? Sep 4, 2017 at 11:06
  • check my updated answer. Sep 4, 2017 at 11:10
  • can any one give me permanent solution, without changing in core file? Sep 4, 2017 at 11:19
0

I am not sure this is right solution but this can solve problem without changing in core file.

I used plugin to override method.

Declare plugin di.xml file.

app/code/Package/Module/etc/di.xml

<type name="Magento\Framework\Data\Collection\AbstractDb">
    <plugin name="Package_Module_Framework_Data_Collection_AbstractDb" type="Package\Module\Plugin\Framework\Data\Collection\AbstractDb" sortOrder="10" disabled="false"  />
</type>

Then create plugin file in

app/code/Package/Module/Plugin/Framework/Data/Collection/AbstractDb.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

namespace Package\Module\Plugin\Framework\Data\Collection;

class AbstractDb
{
    public function afterGetSize(
        \Magento\Framework\Data\Collection\AbstractDb $AbstractDb,
        $totalRecords) {

        $this->_totalRecords = $totalRecords;
        if($this->_totalRecords == 1)
        {
            $sql = $AbstractDb->getSelectCountSql();
            $this->_totalRecords = $AbstractDb->getConnection()->fetchAll($sql);
            //$this->_totalRecords = $AbstractDb->getConnection()->fetchAll($sql,$AbstractDb->_bindParams);
            $this->_totalRecords = count($this->_totalRecords);
        }
        return (int) $this->_totalRecords;

    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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