4

I created a custom price filter (without layered navigation). This function works great on simple products, but configurable products are filtered (maybe because they don't have a price?).

This is my function:

<?php namespace Silvan\Sidebar\Model\Plugin;

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

class SidebarFilter
{
    public function aroundAddFieldToFilter(ProductCollection $collection, \Closure $proceed, $fields, $condition = null)
    {
        if ($fields === 'category_ids') {

            $price  = isset($_GET[ 'price' ]) ? $_GET[ 'price' ] : false;

            if ($price && strpos($price, '-') !== false) {
                $price = explode('-', $price);
                $min   = isset($price[ 0 ]) ? $price[ 0 ] : 0;
                $max   = isset($price[ 1 ]) ? $price[ 1 ] : 9999999;

                $collection->addAttributeToFilter('price', ['gt' => $min]);
                $collection->addAttributeToFilter('price', ['lt' => $max]);
            }
        }

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

I tried using min_price and max_price, but these attributes are ignored in the filter.

2
  • You should use addPriceDataFieldFilter to filter on min_price range Mar 7, 2018 at 9:32
  • Hey @silvan I am facing similar issue mine is price filter doesn't count the configurable products lets say between $50 - $100 will only show simple products and ignore the configurable. your plugin solution don't seem to work
    – Mr F8
    Jul 2, 2020 at 14:02

3 Answers 3

3
+100

Your code did not for simple products too (because it not include data from special price, tear price, required options, catalog price rules).

Magento using price index mechanism to pre-calculate price for a product. See catalog_product_index_price table. The field min_price contains the minimal possible price for product and layered navigation use this field for filtering.

So, try replace in your code

$collection->addAttributeToFilter('price', ['gt' => $min]);
$collection->addAttributeToFilter('price', ['lt' => $max]);

on

$collection->addFieldToFilter('price', ['from' => $min, 'to' => $max]);
4
  • Thank you, I already fixed my problem by using ` $select = $collection->getSelect(); $select->where('price_index.min_price >= ' . $min); $select->where('price_index.min_price < ' . $max);`. Your answer does also work.
    – Silvan
    Jul 4, 2016 at 14:54
  • I am having similar problem if you still have this solution can you send me the plugin so i can test it ?
    – Mr F8
    Jul 2, 2020 at 14:03
  • @Silvan I tried your approach $select = $collection->getSelect(); $select->where('price_index.min_price >= ' . $min); $select->where('price_index.min_price < ' . $max); echo'<pre>';print_r($select->getData());die; But got error main.CRITICAL: Unrecognized method 'getData()' Feb 22, 2023 at 6:08
  • @KAndy also your suggestion does not worked. It still fetch Simple products and ignore Configurable products. Feb 22, 2023 at 6:12
4

Try this code, it filters on min_price range used by configurable products:

class Related extends \Magento\Framework\View\Element\Template
{
  public function __construct(
    \Magento\Backend\Block\Template\Context $context,
    \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
    \Magento\Catalog\Model\Product\Attribute\Source\Status $productStatus,
    \Magento\Catalog\Model\Product\Visibility $productVisibility,
    \Magento\Framework\Registry $registry,
    array $data = []
  )
  {
    $this->_productCollectionFactory = $productCollectionFactory;
    $this->productStatus = $productStatus;
    $this->productVisibility = $productVisibility;
    $this->_registry = $registry;
    parent::__construct($context, $data);
  }

  public function getProductCollection()
  {
    try {

      $product = $this->_registry->registry('current_product');

      $range_percentage = 35;
      $price_temp = round($product->getFinalPrice() / 100 * $range_percentage);
      $price_from = $product->getFinalPrice() - $price_temp;
      $price_to = $product->getFinalPrice() + $price_temp;

      $categories = $product->getCategoryIds();

      $collection = $this->_productCollectionFactory->create();
      $collection->addAttributeToSelect('*')
        ->addCategoriesFilter(['in' => $categories])
        ->addPriceDataFieldFilter('%s >= %s', ['min_price', $price_from])
        ->addPriceDataFieldFilter('%s <= %s', ['min_price', $price_to])
        ->addMinimalPrice()
        ->addAttributeToFilter('entity_id', ['neq' => $product->getId()])
        ->addAttributeToFilter('status', ['in' => $this->productStatus->getVisibleStatusIds()])
        ->setVisibility($this->productVisibility->getVisibleInSiteIds())
        ->setPageSize(5);

      return $collection;

    } catch (\Exception $e) {

      var_dump($e->getMessage());
    }
  }
}
1

Configurable products are filtered (maybe because they don't have a price?). > You're right.

I have exactly the same issue when filtering quantity (qty).

Configurable products quantity is 0.

I don't think the team who designed Magento 2 handled this feature to be able to filter by configurable products children attributes.

We will have to analyze the vendor source code to figure out if they did it somewhere somehow.

Another possible fix would be to set price/quantity of configurable products manually by fetching its children attributes. Maybe a custom script/command we could then put into a cron after each stock update/import.

1
  • i need something that show custom attribute price on filtered config products for exmple i have a configurable product which has size X for $10 XL for $20 XXL for $30 default selected is X ($10) so when i click on XXL in layred navigation it shows me products which has XXL attribute but the price on the products are 10$ do you have any solution or any extension for this :) thanks Oct 18, 2021 at 9:15

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.