I am trying to write a module that filters products in a product collection. For that I have tried to override Magento\Catalog\Model\Layer. These are the files in the module:




<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Model\Layer" type="Viking\FilterProducts\Model\Layer" />


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Viking_FilterProducts" setup_version="1.0.0"/>



namespace Viking\FilterProducts\Model;

class Layer extends \Magento\Catalog\Model\Layer{

    protected $_customerSession;

    protected $_resource;

    public function __construct(
        \Magento\Catalog\Model\Layer\ContextInterface $context,
        \Magento\Catalog\Model\Layer\StateFactory $layerStateFactory,
        AttributeCollectionFactory $attributeCollectionFactory,
        \Magento\Catalog\Model\ResourceModel\Product $catalogProduct,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Registry $registry,
        CategoryRepositoryInterface $categoryRepository,
        array $data = []
        ) {
            $this->_resource = $resource;
            $this->_customerSession = $customerSession; 

    //Old funciton with print statement
    public function getProductCollection(){

        if (isset($this->_productCollections[$this->getCurrentCategory()->getId()])) {
            $collection = $this->_productCollections[$this->getCurrentCategory()->getId()];
        } else {
            $collection = $this->collectionProvider->getCollection($this->getCurrentCategory());
            //Will filter products here
            $this->_productCollections[$this->getCurrentCategory()->getId()] = $collection;

        echo 'New Layer <br />';

        return $collection;


It is still the old Layer that is called. I have overridden other classes in the same way but this time it doesn't work and I don't know why.Been stuck at this point really long now. No error messages.

removing constructor (which will be used) does not make any difference.


I changed the module.xml file as @dersam suggested but it did not help. I also added an composer.json file in Viking/FilterProducts that look like this:

    "name": "Viking/FilterProducts",
    "type": "magento2-module",
    "version": "1.0.0",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/module-catalog": "~100.0"

This did not make any difference either but I am not sure if it is correct. (I ran disable/enable command and then setup and compile commands). The module shows up as enabled when running module:status.


I think I know the problem. You are overriding the incorrect class. Layer model used in layered navigation is created in a constructor of Magento\LayeredNavigation\Block\Navigation class by this piece of code

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Resolver $layerResolver,
    \Magento\Catalog\Model\Layer\FilterList $filterList,
    \Magento\Catalog\Model\Layer\AvailabilityFlagInterface $visibilityFlag,
    array $data = []
) {
    $this->_catalogLayer = $layerResolver->get();
    $this->filterList = $filterList;
    $this->visibilityFlag = $visibilityFlag;
    parent::__construct($context, $data);

$layoutResolver->get() method looks like this:

public function get()
    if (!isset($this->layer)) {
        $this->layer = $this->objectManager->create($this->layersPool[self::CATALOG_LAYER_CATEGORY]);
    return $this->layer;

So it creates a class based on a list of layerPool property which is set in layoutResover class constructor. By default this array contain 2 values:

     'category' => 'Magento\Catalog\Model\Layer\Category',
     'search' => 'Magento\Catalog\Model\Layer\Search'

So either create a preference for the class you want to change it, probably Magento\Catalog\Model\Layer\Category or change the class name passed to layoutResolver class. The original setup can be found in Magento_Catalog/etc/di.xml:

<type name="Magento\Catalog\Model\Layer\Resolver">
        <argument name="layersPool" xsi:type="array">
            <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\Category</item>
            <item name="search" xsi:type="string">Magento\Catalog\Model\Layer\Search</item>
  • Yes! That was the problem. Thank you very much! – Rickard Johansson Apr 13 '17 at 17:40
  • how to change the class name passed to layoutResolver class? I add <item name="outlet" xsi:type="string">Magento\Catalog\Model\Layer\Outlet</item> but still get Magento\Catalog\Model\Layer\Category – krybbio Jun 14 '20 at 6:39
  • @krybbio it won't work that way. This settings sets 2 keys in the layersPool, category and search. Magento internally accesses them by that key. Your config adds new item to the pool but no code uses it. If you want to use different object you need to overwrite the key depending where you want to use your class. – Zefiryn Jul 13 '20 at 20:56
  • @Zefiryn, you're right. it must be declared in controller: public function execute() { $this->layerResolver->create('outlet'); $this->_view->loadLayout(); $this->_view->renderLayout(); } – krybbio Jul 14 '20 at 6:59

Your module doesn't depend on Magento_Catalog. It's possible that the base catalog preference is being merged into the xml after yours, which would cause yours to be ignored.

Try adding Magento_Catalog as a dependency in your module.xml.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Viking_FilterProducts" setup_version="1.0.0">
        <module name="Magento_Catalog" />

See http://devdocs.magento.com/guides/v2.0/extension-dev-guide/build/module-load-order.html.

  • Also check if your module is enabled with php bin/magento module:status – Zefiryn Apr 12 '17 at 17:16
  • The module is enabled when running model status @Zefiryn – Rickard Johansson Apr 13 '17 at 16:18
  • Thanks for the response! I added the xml code and disable/enabled the module, then ran setup and compile commands but it still doesn't work. In the link they mention that one might have to use a composer.json. I tried adding one but I don't know if it is right – Rickard Johansson Apr 13 '17 at 16:21
  • Try move preference to Viking/FilterProducts/etc/frontend/di.xml – Zefiryn Apr 13 '17 at 16:51
  • @Zefiryn I tried moving di.xml to Viking/FilterProducts/etc/frontend but no difference – Rickard Johansson Apr 13 '17 at 17:11

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.