Add a Magento 2 Admin Menu Item

When developers add admin modules to Magento, they may want to know how to add a Magento 2 admin menu item in order to display some custom module content to the user.

The method of doing this is not too dissimilar of how menu items were added in 1.x Magento versions. Instead of adding XML configuration within an adminhtml.xml, we are writing configuration within a menu.xml file.

An simple example of how this is done can be seen below.

Firstly, let’s assume that we are adding a completely new module. We need to start with the module.xml file.

// app/code/Siphor/Adminmenu/etc/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="Siphor_Adminmenu" setup_version="1.0.0" />
</config>

Then add the module’s registration.php file.

// app/code/Siphor/Adminmenu/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Siphor_Adminmenu',
    __DIR__
);

Then, run the following commands to enable your module.

$ /path/to/your/php bin/magento module:enable --clear-static-content Siphor_Adminmenu
$ /path/to/your/php bin/magento setup:upgrade

As mentioned previously, menu items within Magento 2 are added via a menu.xml file. The menu.xml file contains a collection of <add> nodes, each of them defining a menu item that is present on the left hand side of the admin area.

// app/code/Siphor/Adminmenu/etc/adminhtml/menu.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <add id="Siphor_Adminmenu::adminmenu_parent"
             title="Example"
             module="Siphor_Adminmenu"
             sortOrder="999"
             resource="Siphor_Adminmenu::adminmenu_parent"
        />
    </menu>
</config>

Refreshing your Magento admin, you should see that a new menu item is present at the bottom!

Add a Magento 2 Admin Menu Item

This appears at the bottom as we have defined the ‘sortOrder’ attribute value to be higher than any of the other Magento menu items.

You’ll also notice a default menu icon used here. In our example, this icon could be changed by adding a css rule to the ‘.item-adminmenu-parent’ selector. Each menu item is prefixed with an ‘item-‘ class, and the ‘adminmenu-parent’ suffix comes from the <add> node within the menu.xml file.

At the moment the link doesn’t go anywhere. This is because currently, we don’t have an ‘action’ attribute

We can add this to the <add> node as follows.

// app/code/Siphor/Adminhtml/etc/adminhtml/menu.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <add id="Siphor_Adminmenu::adminmenu_parent"
             title="Example"
             module="Siphor_Adminmenu"
             sortOrder="999"
             resource="Siphor_Adminmenu::adminmenu_parent"
             action="adminmenu/page/index"
        />
    </menu>
</config>

So, our action is ‘adminmenu/page/index’ which means that we’ll need to add an adminhtml controller to deal with this route.

Create a routes.xml file within the ‘etc/adminhtml/’ directory of your module structure.

// app/code/Siphor/Adminmenu/etc/adminhtml/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="admin">
        <route id="adminmenu" frontName="adminmenu">
            <module name="Siphor_Adminmenu" />
        </route>
    </router>
</config>

Now add the controller class. Note that adminhtml controllers belong in an ‘Adminhtml’ directory. In addition, don’t forget the controller classes also extend Magento\Backend\App\Action.

// app/code/Siphor/Adminmenu/Controller/Adminhtml/Page/Index.php
<?php
namespace Siphor\Adminmenu\Controller\Adminhtml\Page;

class Index extends \Magento\Backend\App\Action
{
    public function execute()
    {
        echo "We are here!";
        exit();
    }
}

Now if you click on the menu item in your admin area, you should notice the ‘We are here!’ text printed out on your screen.

Magento 2’s admin also provides the ability to add secondary and tertiary menu items without having to clog up the left menu with items for every time you want to add a menu item.

So an example of the menu.xml file when adding a child menu item might look like the following.

// app/code/Siphor/Adminhtml/etc/adminhtml/menu.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <add id="Siphor_Adminmenu::adminmenu_parent"
             title="Example"
             module="Siphor_Adminmenu"
             sortOrder="9999"
             resource="Siphor_Adminmenu::adminmenu_parent"
        />
        <add id="Siphor_Adminmenu::adminmenu_child"
             title="Child Example"
             module="Siphor_Adminmenu"
             sortOrder="9999"
             resource="Siphor_Adminmenu::adminmenu_child"

             parent="Siphor_Adminmenu::adminmenu_parent"
             action="adminmenu/page/index"
        />
    </menu>
</config>

Child menu items can be associated with parent menu items using the ‘parent’ attribute. The attribute value has to match the ‘id’ given to the parent menu item.

Also note that the ‘action’ attribute has been removed from the parent menu item and added to the child menu item.

Now you should be able to see your menu item expand to show the child menu item.

Add a Magento 2 Admin Menu Item

That covers the basics of adding menu items in Magento 2. Of course, you’ll want to set up correct ACL roles, which is what the ‘resource’ attribute is used for. This is covered in the Access Control Lists in Magento 2 article.

Note: This article is based on Magento CE version 2.1.