0

In Category list view I want to create a custom collection where some products are not shown OR the entire collection is re-sorted. To test this I created an observer for the event catalog_block_product_list_collection and modified the collection removing all simple products with the following code :

 /**
 * Execute observer
 *
 * @param \Magento\Framework\Event\Observer $observer
 * @return void
 */
public function execute(
    \Magento\Framework\Event\Observer $observer
) {

    $productCollection = $observer->getEvent()->getCollection();

    if ($productCollection instanceof \Magento\Framework\Data\Collection) {

        foreach ($productCollection as $k => $product){

            if ($product->getTypeId()==='simple')
            {
                $productCollection->removeItemByKey($k);
            }
        }

    }

}

The collection is modified but the original collection size is not updated resulting in the frontend pagination showing 24 products, but listing only 10.

When I try and sort this collection at this point either via the observer or directly in the core code only the first page of the collection is sorted and not the entire collection.

It seems that the collection being passed to the observer is just the paginated collection for the frontend list. I need to modify the entire product collection as it is made, either by removing products or re-sorting the collection.

How can I correctly remove products or re-sort the entire product list collection so that the modified collection properties are correct i.e. collection size, and displayed normally with the correct pagination in the frontend?

  • I do not think this right point to modify the collection – Amit Bera Sep 4 at 8:31
  • Why you don't use a filter function, for example something like $productCollection->addFieldToFilter('type_id', array('neq' => 'simple')); ? – HelgeB Sep 4 at 10:13
  • @AmitBera where would be the right place to change the collection ? – paj Sep 8 at 10:56
0

This is a suggestion. Seems it wont have any repercussion. Comments are welcome.

When magento2 dispatches catalog_block_product_list_collection event it has already applied sort,toolbar etc on the collection. So this wont work.

_getProductCollection this is the function which provides the collection and as its a protected one, you cant use plugin on it.

So how about creating a new class like below which will extend \Magento\Catalog\Block\Product\ListProduct and you define your logic inside the _getProductCollection function.

namespace Namespace\Module\Block\Product;

use Magento\Catalog\Model\Product;
use Magento\Framework\DataObject\IdentityInterface;

/**
 * Product list
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class ListProductNew extends \Magento\Catalog\Block\Product\ListProduct
{

    /**
     * Retrieve loaded category collection
     *
     * @return AbstractCollection
     */
    protected function _getProductCollection()
    {
       /* Whole function code will be here and then you will apply your logic like below */
        $this->_productCollection->addAttributeToFilter('type_id', array('neq' => 'simple'));
        return $this->_productCollection;
    }
}

And then you call this block to provide the data. In this way you are not using a preference and not changing core logic and the core logic will work everywhere else as default except for this case.

  • Thanks for your answer, I will test it - however this post seems to indicate the problem lies with catalog search being used magento.stackexchange.com/questions/172690/… – paj Sep 13 at 9:05
  • try it and let me know – Kingshuk Deb Sep 13 at 9:26
  • Unfortunately this does not work, modifying the collection here is the same as modifying it in the observer - the collection / page size is not updated. – paj Sep 17 at 9:48

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.