I am trying to override the Topmenu Module Block but I can not understand why it fails. I am trying to override the following method:


I have created the following folders/files: app/code/Custom/Theme/Block/Html/Topmenu.php (If it works, "lala" should be appeared at the menu):


namespace Custom\Theme\Block\Html;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
    $html = '';
    if (!$child->hasChildren()) {
        return $html;

    $colStops = null;
    if ($childLevel == 0 && $limit) {
        $colStops = $this->_columnBrake($child->getChildren(), $limit);

    $html .= '<ul class="level' . $childLevel . ' ' . $childrenWrapClass . '">';
    $html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
    $html .= '<li>lala</li></ul>';

    return $html;

protected function _toHtml()
    return parent::_toHtml();


app/code/Custom/Theme/etc/ has two files:

<?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\Theme\Block\Html\Topmenu" type="Custom\Theme\Block\Html\Topmenu" />

<?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="Custom_Theme" setup_version="0.0.1" />

And the registration.php


Is this approach correct? What do I miss?

  • 1
    Did you ever get this working? May 18 '18 at 15:43
  • Did you? I'm working on this right now. Would love to know.
    – JustinP
    Nov 8 '18 at 2:01
  • @JustinP Anyone manage to get this working can you share? Jan 15 '19 at 14:20

You need to specify the usage of the new block via XML. Add the following to your theme's default_head_blocks.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceContainer name="page.top">
      <block class=“Vendor\Module\Block\Html\Topmenu" name="catalog.topnav" template="Magento_Theme::html/topmenu.phtml" ttl="3600" before="-"/>

Move di.xml file from etc folder to etc/frontend folder and clear generated folder. Clear Magento cache. It will work.


2 Things you seem to be correct.

  1. Need to add sequence for Magento_Theme module in your module.xml file
<?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="Ey_Core" setup_version="1.0.0">
            <module name="Magento_Theme"/>
  1. Then you should almost copy the entire Topmenu.php in our module. Because, most of the functions including __addSubMenu() are protected function. No protected functions are rewriteable. Thus we need to rewrite the public function where its being called. Like "getHtml()" function in our case.

Hope this helps anyone in need. 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.