8

This question is about following Magento2 best practices.

I had to rewrite \Magento\Theme\Block\Html\Topmenu::_addSubMenu() method in order to add some wrappers around elements. Now, because it's a protected method, my understanding is that I have to use preference feature:

<preference for="Magento\Theme\Block\Html\Topmenu" type="MyCompany\Theme\Block\Html\Topmenu" />

and add a class with my rewrites:

<?php

namespace MyCompany\Theme\Block\Html;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{
    protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
    {
        // my stuff
    }
}

Although the default class got rewritten, on the next page reload I got the following error:

main.CRITICAL: Invalid template file: 'html/topmenu.phtml' in module: 'MyCompany_Theme' block's name: 'catalog.topnav' [] []

Magento is trying to find html/topmenu.phtml under my extension and not under Magento_Theme. I do understand that this is correct behaviour, but I was thinking about practical aspects of this. Does this mean that whenever we rewrite a block, we need to rewrite its template too, even if we don't necessarily need to touch anything HTML related?

One way around this would be to rewrite _toHtml() method too, like this:

protected function _toHtml()
{
    $this->setModuleName($this->extractModuleName('Magento\Theme\Block\Html\Topmenu'));
    return parent::_toHtml();
}

Now, Magento is looking into Magento_Theme module for the template file again. But, this looks like a hack to me.

So, my question is: what is a recommendation in this situations? Should we always copy relevant template when rewritting block class, or the workaround is fine? Is there a better approach for this?

4

Since there are discussions around the proposed solution in pull request (https://github.com/magento/magento2/pull/1895), meanwhile you just need to "pin" original template when do change of original block class name:

<referenceBlock name="catalog.topnav" class="***" template="Magento_Theme::html/topmenu.phtml"/>
  • This is a good suggestion, although for certain blocks it would be impractical at best since it's used in so many layouts (Catalog\Block\Product\View). I think the OP's suggestion is still the best solution for that instance. – Erfan Feb 25 '17 at 7:00
3

you just need to add one code in this file app/design/frontend/chop/misty/Magento_Theme/layout/default.xml

<referenceBlock name="catalog.topnav" class="Company_name\Override\Block\Html\Topmenu" template="Magento_Theme::html/topmenu.phtml"/>

and add below code in your override module file name : app/code/Aims/Override/etc/di.xml code :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <preference for="Magento\Theme\Block\Html\Topmenu" type="Company_name\Override\Block\Html\Topmenu" />
    <preference for="Magento\Paypal\Model\Config" type="Company_name\Override\Model\Paypal\Config" />
</config>

Add Topmenu.php file in File : app/code/Company_name/Override/Block/Html/Topmenu.php you can add whatever function you want to override.

Thanks

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.