When it comes to Magento customization, every now and then, there’s a need for a custom configuration option that needs to be placed somewhere in the administration menu. Magento 2 comes with well organized admin menu, but what if newly created configuration option doesn’t fit anywhere?
In that case, a new menu item can be created to accommodate that option. Here’s a tutorial on how to do it in Magento 2.
Unlike Magento 1, the admin menu in Magento 2 is located on the left side of the screen. Reason for that is to simplify access to a menu from a tablet or smartphone.
What is a menu item?
Basically, menu item is a link that leads to another admin configuration page. An example of that would be something like this:
Part of this URL is a sales/order/index, which is an area of interest here. It consists of three parts that need to be defined in menu item XML configuration.
Front Name: sales Controller Name: order Action Name: index
There is also a key variable in the link, which serves as a protection from cross site script attacks. This is actually a real reason for menu item to be created the “Magento way”. Any admin request without this variable will be invalidated. Other link parts are created automatically by the Magento.
Create new basic module
In order to demonstrate how menu item is created, a new basic module structure is needed. There’s a nice article on how to create a basic module in Magento 2.
\Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Inchoo_MenuItem', __DIR__ );
<?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="Inchoo_MenuItem" setup_version="1.0.0" /> </config>
Create new menu item
Menus are configured by the file menu.xml which is located in module’s etc/adminhtml folder. It consists of config and menu nodes and add directives. Menu node may consist of multiple add directives.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd"> <menu> <add id="Inchoo_MenuItem::first_level_demo" title="Inchoo First Level" module="Inchoo_MenuItem" sortOrder="9999" resource="Magento_Backend::content" /> </menu> </config>
As it can be seen from the menu.xml structure, new menu item is typically added using an add directive with it’s parameters. It is wrapped up in a menu tag.
Explanation of the directive’s attributes is as follows:
- id – unique node identifier, should follow the format: Vendor_Module::menu_item_description
- title – text that is shown in menu
- module – current module
- sortOrder – where to place menu item
- resource – defines the ACL rule which the admin user must have in order to see and access this menu, it is defined in acl.xml. Otherwise, menu item won’t be rendered. For simplicity, Magento_Backend::content is used.
After running Magento’s CLI command cache:clean, new menu item should be visible. But for now, it leads to nowhere, it is not a hyperlink. It’s not usual for a first level menu items to be hyperlinks, but only to be containers of a second or third levels.
All it takes for a menu item to become an actual link is an action attribute. For menu item that is located on a second level for example, a parent attribute must also be used. It defines on which first level it depends. It can be current module or any other from the menu (e.g. system module Magento_Backend::system). Same logic applies to third level menu item.
- action – defined above, tells Magento to generate link to certain admin controller
- parent – defines on which first level a menu item depends
Example for a second level menu item with an action:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd"> <menu> <add id="Inchoo_MenuItem::first_level_demo" title="Inchoo First Level Item" module="Inchoo_MenuItem" sortOrder="9999" resource="Magento_Backend::content" /> <add id="Inchoo_MenuItem::second_level_demo" title="Inchoo Second Level Item" module="Inchoo_MenuItem" sortOrder="0" action="menuitem/index/index" parent="Inchoo_MenuItem::first_level_demo" resource="Magento_Backend::content" /> </menu> </config>
Flushing the magento cache
After everything is defined, the magento cache should be cleaned with the following CLI command:
php -f bin/magento cache:clean
That’s it. The menu item should now be visible in admin menu under the first level “Inchoo First Level Item” at the end and it should lead to a defined action. In this example, for simplicity, action leads to nowhere because module’s controller should be created.
Here’s how it looks like at the end:
In case you feel you could use some extra help with your Magento 2 project, feel free to reach out. We’ve been a trained Magento 2 partner for quite a while now and we’d like to help you make your shop extraordinary! 🙂