menu.xml Structure
Menu Configuration
<!-- app/code/Vendor/Module/view/adminhtml/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>
<!-- Top-level menu -->
<add id="Vendor_Module::module"
title="Custom Module"
module="Vendor_Module"
sortOrder="100"
resource="Vendor_Module::module"/>
<!-- Submenu item -->
<add id="Vendor_Module::items"
title="Items"
module="Vendor_Module"
sortOrder="10"
parent="Vendor_Module::module"
action="vendor_module/item/index"
resource="Vendor_Module::items_view"/>
<!-- Another submenu -->
<add id="Vendor_Module::settings"
title="Settings"
module="Vendor_Module"
sortOrder="20"
parent="Vendor_Module::module"
action="vendor_module/settings/index"
resource="Vendor_Module::settings"/>
</menu>
</config>
Menu Attributes
| Attribute | Description |
|---|---|
| id | Unique menu identifier |
| title | Display text |
| module | Module name |
| sortOrder | Order in menu |
| parent | Parent menu ID |
| action | Controller route |
| resource | ACL resource |
Menu Hierarchy
Multi-Level Menus
<menu>
<!-- Level 1: Top menu -->
<add id="Vendor_Module::main"
title="My Module"
module="Vendor_Module"
sortOrder="100"
resource="Vendor_Module::main"/>
<!-- Level 2: Submenu -->
<add id="Vendor_Module::catalog"
title="Catalog"
module="Vendor_Module"
sortOrder="10"
parent="Vendor_Module::main"
resource="Vendor_Module::catalog"/>
<!-- Level 3: Sub-submenu -->
<add id="Vendor_Module::products"
title="Products"
module="Vendor_Module"
sortOrder="10"
parent="Vendor_Module::catalog"
action="vendor_module/product/index"
resource="Vendor_Module::products_view"/>
<add id="Vendor_Module::categories"
title="Categories"
module="Vendor_Module"
sortOrder="20"
parent="Vendor_Module::catalog"
action="vendor_module/category/index"
resource="Vendor_Module::categories_view"/>
</menu>
Menu Structure Example
My Module (Vendor_Module::main)
├── Catalog (Vendor_Module::catalog)
│ ├── Products (→ vendor_module/product/index)
│ └── Categories (→ vendor_module/category/index)
├── Orders (Vendor_Module::orders)
│ ├── All Orders (→ vendor_module/order/index)
│ └── Pending (→ vendor_module/order/index/status/pending)
└── Settings (→ vendor_module/settings/index)
Menu Actions
Menu with Action URL
<!-- Direct action URL -->
<add id="Vendor_Module::reports"
title="Reports"
module="Vendor_Module"
sortOrder="30"
parent="Vendor_Module::main"
action="vendor_module/report/sales"
resource="Vendor_Module::reports"/>
<!-- Action with parameters -->
<add id="Vendor_Module::filtered_orders"
title="Pending Orders"
module="Vendor_Module"
sortOrder="10"
parent="Vendor_Module::orders"
action="vendor_module/order/index/status/pending"
resource="Vendor_Module::orders_view"/>
Dynamic Menu Items
// Generate menu items dynamically
namespace Vendor\Module\Menu\Provider;
class MenuProvider implements \Magento\Framework\Menu\Item\InterfaceProvider
{
public function __construct(
private \Magento\Framework\Menu\ConfigInterface $menuConfig
) {}
public function getItems(): array
{
$items = [];
// Add dynamic items based on configuration
$categories = $this->getCategories();
foreach ($categories as $category) {
$items[] = [
'id' => 'vendor_module::category_' . $category->getId(),
'title' => $category->getName(),
'module' => 'Vendor_Module',
'sortOrder' => $category->getSortOrder(),
'parent' => 'Vendor_Module::categories',
'action' => 'vendor_module/category/view/id/' . $category->getId(),
'resource' => 'Vendor_Module::categories_view',
];
}
return $items;
}
}
Menu Customization
Remove Menu Items
<!-- Remove existing menu items -->
<menu>
<!-- Remove specific item -->
<remove id="Magento_Cms::cms"/>
<!-- Remove by parent -->
<remove id="Magento_Backend::content"/>
</menu>
Override Menu Items
<!-- Override existing menu item -->
<menu>
<add id="Magento_Sales::sales"
title="Sales (Custom)"
sortOrder="50"
resource="Magento_Sales::sales"/>
</menu>
Menu ACL Integration
// Check if user can see menu item
$isVisible = $this->authorization->isAllowed('Vendor_Module::items_view');
if ($isVisible) {
// Show menu item
}
Menu in Layout XML
<!-- Add block to menu area -->
<referenceContainer name="menu">
<block class="Vendor\Module\Block\Menu\Custom"
name="custom_menu_block"
template="Vendor_Module::menu/custom.phtml"/>
</referenceContainer>
Quiz
1. What file configures admin menus?
2. How do you link a menu item to a controller?
3. What does the resource attribute control?
Flashcards
Question
Menu config file?
Click to reveal answer
Answer
view/adminhtml/menu.xml
Question
Menu item link attribute?
Click to reveal answer
Answer
action (e.g., vendor_module/controller/action)
Question
Menu visibility control?
Click to reveal answer
Answer
resource attribute for ACL permission
Question
How to nest menus?
Click to reveal answer
Answer
Use parent attribute to reference parent menu id
Revision Notes
Key Takeaways
- 1. menu.xml defines admin menu structure and items
- 2. Items are linked to controllers via the action attribute
- 3. ACL resources control menu visibility per user role
- 4. Menus support multi-level hierarchy via parent references
- 5. Menu items can be removed or overridden by other modules
Interview Tips
- • Explain the menu.xml structure and attributes
- • Describe how to add a custom menu section
- • Discuss ACL integration for menu visibility
Cheat Sheet
Admin Menus:
File: view/adminhtml/menu.xml
Structure: <add> elements with id, title, parent
Link: action="route/controller/action"
ACL: resource="Vendor_Module::permission"
Attributes:
id: unique identifier
title: display text
parent: parent menu id
sortOrder: display order
resource: ACL resource