menu.xml Structure
menu.xml defines the admin navigation menu structure.
Basic menu.xml:
<?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 under existing top-level item -->
<add id="Vendor_Blog::blog" title="Blog" module="Vendor_Blog"
sortOrder="80" resource="Vendor_Blog::blog"/>
<!-- Add child items -->
<add id="Vendor_Blog::blog_posts" title="Posts" module="Vendor_Blog"
sortOrder="10" parent="Vendor_Blog::blog" resource="Vendor_Blog::blog_posts"/>
<add id="Vendor_Blog::blog_categories" title="Categories" module="Vendor_Blog"
sortOrder="20" parent="Vendor_Blog::blog" resource="Vendor_Blog::blog_categories"/>
<add id="Vendor_Blog::blog_settings" title="Settings" module="Vendor_Blog"
sortOrder="30" parent="Vendor_Blog::blog" resource="Vendor_Blog::blog_settings"/>
</menu>
</config>
Menu attributes:
| Attribute | Description |
|---|---|
id |
Unique menu item identifier |
title |
Display text |
module |
Module that owns this item |
sortOrder |
Display order within parent |
parent |
Parent menu item ID |
resource |
ACL resource for visibility |
action |
URL action path |
titleTranslated |
Translation key (optional) |
Menu hierarchy:
Content (Magento_Cms)
├── Pages
├── Blocks
└── Blog (Vendor_Blog) ↠custom
├── Posts
├── Categories
└── Settings
ACL Integration
Menu items are only visible if the user has the required ACL resource.
ACL-controlled menu:
<add id="Vendor_Blog::blog" title="Blog" module="Vendor_Blog"
sortOrder="80" resource="Vendor_Blog::blog"/>
Without ACL (visible to all):
<!-- No resource attribute = always visible -->
<add id="Vendor_Blog::blog" title="Blog" module="Vendor_Blog"
sortOrder="80"/>
ACL hierarchy:
<!-- If user has Vendor_Blog::blog, they see all children -->
<add id="Vendor_Blog::blog" resource="Vendor_Blog::blog"/>
<add id="Vendor_Blog::posts" parent="Vendor_Blog::blog" resource="Vendor_Blog::blog_posts"/>
<add id="Vendor_Blog::settings" parent="Vendor_Blog::blog" resource="Vendor_Blog::blog_settings"/>
Restricting menu items:
<!-- Only admin users with catalog permission see this -->
<add id="Vendor_Blog::import" title="Import" module="Vendor_Blog"
parent="Magento_Catalog::catalog" resource="Magento_Catalog::catalog_products"/>
Debugging menu visibility:
# Check admin role permissions
php bin/magento admin:roles:list
# Verify ACL resources
grep -r "Vendor_Blog::" app/code/Vendor/Blog/etc/acl.xml
# Check menu registration
php bin/magento dev:module:list --enabled | grep Vendor_Blog
Menu Positioning and Icons
Control menu item positioning and visual appearance.
Sort order examples:
<!-- Content section approximate sort orders -->
Magento_Cms::cms → 20
Magento_Catalog::catalog → 30
Vendor_Blog::blog → 80 (appears after catalog)
Adding to existing sections:
<!-- Add under Sales -->
<add id="Vendor_Blog::sales_blog" title="Blog Orders" module="Vendor_Blog"
parent="Magento_Sales::sales" sortOrder="50" resource="Vendor_Blog::blog"/>
<!-- Add under Marketing -->
<add id="Vendor_Blog::marketing" title="Blog Marketing" module="Vendor_Blog"
parent="Magento_Marketing::marketing" sortOrder="60"/>
Custom action URLs:
<add id="Vendor_Blog::blog_posts" title="Posts" module="Vendor_Blog"
parent="Vendor_Blog::blog" sortOrder="10"
action="vendor_blog/post/index" resource="Vendor_Blog::blog_posts"/>
Menu icons (CSS):
<!-- Add icon via CSS class -->
<add id="Vendor_Blog::blog" title="Blog" module="Vendor_Blog"
sortOrder="80" resource="Vendor_Blog::blog">
<class>vendor-blog-icon</class>
</add>
/* In admin CSS */
.vendor-blog-icon::before {
content: '\e000'; /* Custom icon */
font-family: 'icons';
}
Removing menu items:
<!-- Remove existing menu item -->
<remove id="Magento_Cms::cms_pages"/>
<!-- Remove entire section -->
<remove id="Magento_Backend::marketing"/>
Dynamic Menu Items
Create menu items dynamically based on configuration or data.
Remove and re-add pattern:
<!-- Remove default, add custom -->
<remove id="Magento_Catalog::catalog_products"/>
<add id="Vendor_Module::catalog_products" title="Products" module="Vendor_Module"
parent="Magento_Catalog::catalog" sortOrder="10"
action="catalog/product" resource="Magento_Catalog::catalog_products"/>
Menu with external link:
<add id="Vendor_Blog::docs" title="Documentation" module="Vendor_Blog"
sortOrder="100" resource="Magento_Backend::admin"
action="https://docs.example.com"/>
Module menu integration:
<!-- Your module adds to third-party menu -->
<add id="Vendor_Extension::thirdparty_section" title="Extensions" module="Vendor_Extension"
parent="ThirdParty_Module::menu" sortOrder="100"/>
Menu debugging:
# View complete menu tree
php bin/magento dev:module:list
# Check if menu item is registered
grep -r "Vendor_Blog::" app/code/Vendor/Blog/etc/menu.xml
# Flush admin cache
php bin/magento cache:clean config
Quiz
1. What XML file defines the admin menu?
2. What attribute controls menu item visibility via permissions?
3. How do you create a child menu item?
4. How do you remove an existing menu item?
Flashcards
Question
What file defines admin menu items?
Click to reveal answer
Answer
menu.xml
Question
How do you make a menu item child of another?
Click to reveal answer
Answer
Set parent="parent_item_id" attribute
Question
What controls menu item visibility?
Click to reveal answer
Answer
resource attribute referencing ACL resources
Question
How do you remove a menu item?
Click to reveal answer
Answer
<remove id="item_id"/>
Question
What does sortOrder control?
Click to reveal answer
Answer
Display order within the parent menu section
Revision Notes
Key Takeaways
- 1. menu.xml defines admin navigation with add and remove elements
- 2. Each item needs id, title, module, and optionally parent/resource
- 3. ACL resources control which users can see menu items
- 4. sortOrder determines display order within parent sections
- 5. Use <remove> to eliminate existing menu items
- 6. Menu items can link to external URLs via action attribute
Interview Tips
- • Explain how to add custom menu items
- • Describe ACL-based menu visibility
- • Know how to remove or replace existing menu items
- • Discuss menu positioning with sortOrder
Cheat Sheet
menu.xml Cheat Sheet
Add item:
<add id="Vendor_Module::section" title="Title" module="Vendor_Module"
parent="Magento_Backend::admin" sortOrder="100"
resource="Vendor_Module::resource"/>
Remove item:
<remove id="Magento_Cms::cms_pages"/>
Attributes:
- id: Unique identifier
- title: Display text
- parent: Parent menu item ID
- sortOrder: Display order
- resource: ACL resource
- action: URL action path
ACL: resource controls visibility