I am overriding Magento\Catalog\Block\Product\ListProduct In function _getProductCollection I have added some extra code.

public function _getProductCollection()
 $collection = parent::_getProductCollection(); 
 $collection->addAttributeToFilter('attribute', array('operator' =>
    return $collection  

But my collection in not attaching this attribute. I am getting only default collection except adding operator attribute

Any idea ??

  • Instead of $collection->addAttributeToFilter('attribute', array('operator' => 'value')) try this $collection->addAttributeToFilter('operator', 'value') – Amit Naraniwal Feb 7 at 8:57
  • How are you overriding the method? Using a preference? Perhaps you should try using a plugin, something like public function afterGetLoadedProductCollection() which only calls the protected function you're trying to override and returns a collection instance. Then you can try adding the attribute you need. Furthermore check the attribute settings. It must be used in product listing. – Zankar Feb 7 at 8:58

First of all, your method should be compatible with the original method. So you should make it protected instead of public.

Now the problem.. The original _getProductCollection calls initializeProductCollection from the same class.
This method dispatches an event that can be used to alter the collection.

        ['collection' => $collection]

So far so good.
Not the real problem.
There is an observer that hooks into this event.
In the review module in frontend/events.xml there is this:

<event name="catalog_block_product_list_collection">
    <observer name="review" instance="Magento\Review\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver" shared="false" />

and the observer method looks like this:

public function execute(\Magento\Framework\Event\Observer $observer)
    $productCollection = $observer->getEvent()->getCollection();
    if ($productCollection instanceof \Magento\Framework\Data\Collection) {

    return $this;

As you can see, there is this line $productCollection->load();.
This actually executes the sql query from the collection and loads the products from the db.
Any other modifications you add to the collection after load is called (or after the collection gets iterated) is useless. It will not affect the collection in any way.

Possible solutions:

  1. Create a before plugin for the Magento\Review\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver::execute method and attach your filter to the collection. But this is not really that clean and it doesn't insure that there will be no other events that do the same. This would only work if the observer mentioned above is run before any other observer that might call load on the collection. If you don't have such modules, you should be safe, but if you install one in the future it might take a lot of time to identify the problem.

  2. Create an after on the method Magento\Catalog\Model\Layer::getProductCollection that gets executed inside the method you are changing. But this may (or may not) have side effects and change the collection in other places.

  3. There may be other solutions that I don't know of.

  • I am not quite sure if we can create plugin for Magento\Catalog\Model\Layer – Daniel_12 Feb 7 at 9:08
  • 1
    technically or business wise? Technically is possible. – Marius Feb 7 at 9:12
  • whats the best solution for this? – Daniel_12 Feb 7 at 9:14
  • I don't know. I would go with the plugin on the layer model. but I would check for side effects. I don't know where to tell you to look because I don't know the business case. – Marius Feb 7 at 9:16
  • I created obsever on catalog_block_product_list_collection event and good part is that works – Daniel_12 Feb 7 at 12:05

I created observer for catalog_block_product_list_collection and added my filter there and am able to get the desired products

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.