0

I want to have a filter by product rating in layered navigation. Regarding this, I found a solution Magento 2 : Rating Filter in Layered Navigation. This is working fine if you modify vendor\magento\module-catalog\Model\Layer\FilterList.php in core folder(vendor folder). But I'm not able to override vendor\magento\module-catalog\Model\Layer\FilterList.php from app/code. Please share if anybody has any suggestion. Thanks in advance.

1 Answer 1

0

try this

Create a module and add the below files. Create plugin to override FilterList.php

File:- Vendor/Module/Model/Layer/Filter/Rating.php

This file code available here enter link description here

<?php

namespace Vendor\Module\Model\Layer\Filter;

use Magento\Catalog\Model\Category as CategoryModel;
use Magento\Catalog\Model\CategoryFactory as CategoryModelFactory;
use Magento\Catalog\Model\Layer;
use Magento\Framework\Registry;

class Rating extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter
{

    protected $_categoryId;
    protected $_appliedCategory;
    protected $_escaper;
    protected $_coreRegistry;
    private $dataProvider;

    public function __construct(
        \Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Catalog\Model\Layer $layer,
        \Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder,
        \Magento\Framework\Escaper $escaper,
        array $data = []
    ) {
        parent::__construct($filterItemFactory, $storeManager, $layer, $itemDataBuilder, $data);
        $this->_escaper = $escaper;
        $this->_requestVar = 'rat';
    }

    public function getResetValue()
    {
        return $this->dataProvider->getResetValue();
    }

    public function apply(\Magento\Framework\App\RequestInterface $request)
    {

        $filter = $request->getParam($this->getRequestVar());
        if (!$filter) {
            return $this;
        }
        $filter = explode('-', $filter);
        list($from, $to) = $filter;
         $collection = $this->getLayer()->getProductCollection();

        $collection->getSelect()->joinLeft(array('rova'=> 'rating_option_vote_aggregated'),'e.entity_id =rova.entity_pk_value',array("percent"))
        ->where("rova.percent between ".$from." and ".$to)
        ->group('e.entity_id'); 
        return $this;
    }

    public function getName()
    {
        return __('Rating');
    }

    protected function _getItemsData()
    {

        $facets = array(
            '0-20'=>'1 Start',
            '21-40'=>'2 Start',
            '41-60'=>'3 Start',
            '61-80'=>'4 Start',
            '81-100'=>'5 Start'
            );
     $collection = $this->getLayer()->getProductCollection();
        $data = [];
        if (count($facets) > 1) { // two range minimum
            $i=1;
            foreach ($facets as $key => $label) {
               $count=$this->prepareData($key,$collection,$i);
               $i++;
               $this->itemDataBuilder->addItemData(
                    $this->_escaper->escapeHtml($label),
                    $key,
                    $count
                );
            }
        }

        return $this->itemDataBuilder->build();
    }

    private function prepareData($filter,$collection,$i)
    {
       $filter = explode('-', $filter);
        list($from, $to) = $filter;

        $collection->getSelect()->joinLeft(array('rova'.$i=> 'rating_option_vote_aggregated'),'e.entity_id =rova'.$i.'.entity_pk_value',array("percent"))
        ->where("rova".$i.".percent between ".$from." and ".$to)
        ->group('e.entity_id'); 
        return $collection->getSize();
    }
}

File:- Vendor/Module/etc/frontend/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">

    <type name="Magento\Catalog\Model\Layer\FilterList">
        <plugin name="rating-filter-category-navigation" type="Vendor\Module\Model\Plugin\FilterList" />
    </type>

</config>

File:- Vendor/Module/Model/Plugin/FilterList.php

<?php

namespace Vendor\Module\Model\Plugin;

class FilterList
{
    protected $_objectManager;

    protected $_layer;

    protected $_storeManager;

    protected $_stockResource;

    protected $_scopeConfig;

    public function __construct(
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\ObjectManagerInterface $objectManager,
        \Magento\CatalogInventory\Model\Resource\Stock\Status $stockResource,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    ) {
        $this->_storeManager = $storeManager;
        $this->_objectManager = $objectManager;
        $this->_stockResource = $stockResource;
        $this->_scopeConfig = $scopeConfig;
    }

   public function afterGetFilters(
\Magento\Catalog\Model\Layer $layer 
) {

    if (!count($this->filters)) {
        $this->filters = [
            $this->objectManager->create($this->filterTypes[self::CATEGORY_FILTER], ['layer' => $layer]),
        ];
        foreach ($this->filterableAttributes->getList() as $attribute) {
            $this->filters[] = $this->createAttributeFilter($attribute, $layer);
        }
    }
    $data = array_shift($this->filters);
    $this->filters[]=  $data;
    return $this->filters;
  }
}

I hope this will help you...!

4
  • Yes that's the way I took. But I stuck in the following function public function getFilters(\Magento\Catalog\Model\Layer $layer) { } Here I'm not able to get $this->filterableAttributes->getList() since it's a interface. How to get that value in app/code/custom_module
    – Soham.M
    May 28, 2020 at 17:59
  • check this ans magento.stackexchange.com/questions/312680/…
    – Devidas
    May 29, 2020 at 6:53
  • and check I have the update my answer.
    – Devidas
    May 29, 2020 at 6:55
  • Thanks @Devidas for taking time for looking into it. I'm almost there. I followed the link you added in the comment magento.stackexchange.com/questions/312680/…. But I'm getting 500 server error. I checked no other PHP error is there in the code. Can you please tell me apart from the function what should I add in the class. It's a bit more to ask, but if you could tell me it'll be very helpful for me.
    – Soham.M
    May 29, 2020 at 9:05

Your Answer

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

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