Sometimes, we need to add a custom attribute filter in the product list. but we can’t apply attribute filter directly, because when product collection loads there is an event ‘catalog_block_product_list_collection’ fired and an observer Magento\Review\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver executes and it overrides the applied filter.
So, to apply the custom attribute filter, we create a plugin of the execute method of CatalogBlockProductCollectionBeforeToHtmlObserver class.
Note: We can directly add custom attribute filter in Magento version < 2.2.0
So, this process is for Magento version > 2.2.*
So, to add a custom attribute filter, follow the following steps one by one.
1. Create CustomProductList.php file inside Vendor_Module/Block.
<?php namespace Vendor\Module\Block; use Magento\Catalog\Block\Product\ListProduct; use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection; use Magento\Catalog\Api\CategoryRepositoryInterface; class CustomProductList extends ListProduct { public function __construct( \Magento\Catalog\Block\Product\Context $context, \Magento\Framework\Data\Helper\PostHelper $postDataHelper, \Magento\Catalog\Model\Layer\Resolver $layerResolver, CategoryRepositoryInterface $categoryRepository, \Magento\Framework\Url\Helper\Data $urlHelper ) { parent::__construct( $context, $postDataHelper, $layerResolver, $categoryRepository, $urlHelper ); } /** * @return Magento\Eav\Model\Entity\Collection\AbstractCollection */ protected function _getProductCollection() { return parent::_getProductCollection(); } }
2. Create Index.php file inside Vendor_Module/Controller/CustomProductList
<?php namespace Vendor\Module\Controller\CustomProductList; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Index extends Action { /** @varPageFactory */ protected $pageFactory; /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection */ protected $productCollection; public function __construct( Context $context, PageFactory $pageFactory ) { $this->pageFactory = $pageFactory; parent::__construct($context); } public function execute() { $result = $this->pageFactory->create(); return $result; } }
3. Create layout file routename_controllername_actionname.xml (for example: demo_customproductlist_index.xml) file inside Vendor_Module/view/frontend.
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”2columns-left” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”> <head> <title>Custom Product List</title> </head> <body> <referenceContainer name=”content”> <block class=”Vendor\Module\Block\CustomProductList” name=”custom.products.list” as=”product_list” template=”Magento_Catalog::product/list.phtml”> <container name=”category.product.list.additional” as=”additional” /> <block class=”Magento\Framework\View\Element\RendererList” name=”category.product.type.details.renderers” as=”details.renderers”> <block class=”Magento\Framework\View\Element\Template” as=”default”/> </block> <block class=”Magento\Catalog\Block\Product\ProductList\Item\Container” name=”category.product.addto” as=”addto”> <block class=”Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare” name=”category.product.addto.compare”as=”compare” template=”Magento_Catalog::product/list/addto/compare.phtml”/> </block> <block class=”Magento\Catalog\Block\Product\ProductList\Toolbar” name=”product_list_toolbar” template=”Magento_Catalog::product/list/toolbar.phtml”> <block class=”Magento\Theme\Block\Html\Pager” name=”product_list_toolbar_pager”/> </block> <action method=”setToolbarBlockName”> <argument name=”name” xsi:type=”string”>product_list_toolbar</argument> </action> </block> </referenceContainer> </body> </page>
4. Now, we will create the Plugin of CatalogBlockProductCollectionBeforeToHtmlObserver Class, in which we add the custom attribute filter. Here, we add a check for controller action name to avoid this filter in other product lists.
<?php /** * Webkul Software. * * @category Webkul * @package Vendor_Module * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Vendor\Module\Plugin; use \Magento\Framework\App\Helper\Context; class CatalogBlockProductCollectionBeforeToHtmlObserver { /** * Review model * * @var \Magento\Review\Model\ReviewFactory */ protected $_reviewFactory; protected $_request; /** * @param Context $context * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Review\Model\ReviewFactory $reviewFactory */ public function __construct( Context $context, \Magento\Framework\App\RequestInterface $request, \Magento\Review\Model\ReviewFactory $reviewFactory ) { $this->_reviewFactory = $reviewFactory; $this->_request = $request; } public function aroundExecute( \Magento\Review\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver $subject, callable $proceed, \Magento\Framework\Event\Observer $observer ) { $productCollection = $observer->getEvent()->getCollection(); if ($this->_request->getFullActionName() ==”demo_customproductlist_index”) { $productCollection->addAttributeToFilter(‘as_featured’, 1); //adding custom attribute filter in product collection } if ($productCollection instanceof \Magento\Framework\Data\Collection) { $productCollection->load(); $this->_reviewFactory->create()->appendSummary($productCollection); } return $this; } }
5. Finally, we mention this plugin in di.xml file.
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:ObjectManager/etc/config.xsd”>
<type name=”Magento\Review\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver”> <plugin name=”Vendor_Module::aroundExecute” type=”Vendor\Module\Plugin\CatalogBlockProductCollectionBeforeToHtmlObserver” sortOrder=”10″ />
</type>
</config>
Additionally, In above example, I have used the “as_featured” custom attribute. You can create your custom attribute as per your requirement using Setup files or from admin section.
Thanks 🙂

Custom product Collection
Previous Blog: Inspecting developer tools in iPad Device
Next Blog: Profiler in Magento 2
https://bit.ly/2zKgRid