Magento – Magento 2.2 : Search Functionality/Layered Navigation on a Custom Product Collection

catalogsearchcollection;layered-navigationmagento2magento2.2

I use a custom product collection which is used on all category view pages (basically, instead of using Magento's collection, I wrote my own module with the custom collection to implement a cookie-based vehicle filtering system).

I realize that when using a custom collection, the layered navigation, and main product search functionality does not work. Anytime I click a filter on the navigation, it will just show the custom collection without any changes. And when I type in something in the search box, it gets ignored and does not actually filter any products based on what I searched for.

My question is, how do I extend the search functionality and the layered navigation functionalities to cooperate with my custom collection?

EDIT: Here is my full custom product collection code located inside the Block folder in my module (Block/CustomCollection.php):

<?php
namespace Company\CustomCollection\Block;

use Magento\Framework\Registry;
use Magento\Catalog\Block\Product\ListProduct;


class CustomCollection extends \Magento\Catalog\Block\Product\ListProduct
{    
    private $registry;

    public function __construct(Registry $registry, 
         \Magento\Catalog\Block\Product\Context $context,        
        array $data = []
    )
    {    
        $this->registry = $registry;
        parent::__construct($context, $data);
    }

    protected function _prepareLayout()
    {

        parent::_prepareLayout();
        $this->pageConfig->getTitle()->set(__('Productss'));

            return $this;
    }


    public function getLoadedProductCollection()
    {
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $car = $objectManager->get('Module\CarData\Save\Custom')->get("selectedcar");
        $category = $this->registry->registry('current_category');

        if(!empty($data)) {
        $data = array("Toyota"=>"24",  
            "Honda"=>"25", 
            "Lexus"=>"26" 
             );
        $collection = parent::getLoadedProductCollection();
        $collection->addAttributeToFilter('vehicle', array('like' => '%' . $data[$car] . '%'));

        $collection->setPageSize(7); // fetching only 7 products
    } else {
        $collection = parent::getLoadedProductCollection();
        $collection->setPageSize(7); // fetching only 7 products

    }
        return $collection;
    }

}
?>

EDIT: Here is my FULLY FUNCTIONAL CustomLayer.php

<?php
namespace Company\CustomCollection\Plugin;

use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory as AttributeCollectionFactory;
use Magento\Catalog\Model\Layer\ContextInterface;

class Layer
{
  public function aroundGetProductCollection(
    \Magento\Catalog\Model\Layer $subject,
    \Closure $proceed
  ) {

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $car = $objectManager->get('Module\CarData\Save\Custom')->get("selectedcar");
        $result = $proceed();

  if(!empty($data)) {
            $data = array("Toyota"=>"24",  
            "Honda"=>"25", 
            "Lexus"=>"26" 
             );
        $result->addAttributeToFilter('vehicle', array('like' => '%' . $data[$car] . '%'));


} else {
$result->addAttributeToFilter('price', array('lt' => 1201));
}
    return $result;
  }
}

DI.XML

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Block\Product\ListProduct" type="Company\CustomCollection\Block\CustomCollection" />
    <type name="Magento\Catalog\Model\Layer">
    <plugin name="CustomLayer" type="Company\CustomCollection\Plugin\CustomLayer" />
    </type>
</config>

I have literally looked everywhere online, and it seems there is nothing about this. I can't be the only one with this issue. A lot of people utilize their own collections, however, what happens when they need to search or if they need to use the layered navigation filter?!

Any help would be appreciated, thanks!!

Best Answer

You should avoid Object Manager, this is just an untested example based on your code. This goes inside YourNamespace\YourModule\Block\CustomCollection.php. This class also needs to extend \Magento\Catalog\Block\Product\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,
    Registry $registry, 
    array $data = []
) {
    $this->registry = $registry;
    parent::__construct(
        $context,
        $postDataHelper,
        $layerResolver,
        $categoryRepository,
        $urlHelper,
        $data
    );
}
public function getProductCollection()
{
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $car = $objectManager->get('Module\CarData\Save\Custom')->get("selectedcar");
    $data = array("Toyota"=>"24", 
        "Honda"=>"25", 
        "Lexus"=>"26" 
        );
    $collection = parent::getProductCollection();
    $collection->addAttributeToFilter('car', array('like' => '%' . $data[$car] . '%'));

    return $collection;
}

This code assumes you used DI to overwrite core class. In essence, you can tell Magento to use your class instead of his core wherever it is used. I recommend using a plugin for this instance, but you don't need to bother with it. This goes inside YourNamespace\YourModule\etc\frontend\di.xml

<config>
    <preference for="Magento\Catalog\Block\Product\ListProduct" type="YourNamespace\YourModule\Block\CustomCollection" />
</config>

I am unable to test this code at the moment, so it might contain some syntax errors, or the Core class could be wrong. Here is the reference for DI. Magento DI

Related Topic