Skip to main content

Overview

The MenuItem model represents individual items within navigation menus. It supports hierarchical menu structures through parent-child relationships, allowing you to create nested submenus. Namespace: App\Models\MenuItem File: app/Models/MenuItem.php:7

Properties

Fillable attributes

menu_id
integer
required
The ID of the parent menu
label
string
required
The display text for the menu item
url
string
required
The URL or route the menu item links to
parent_id
integer|null
The ID of the parent menu item (null for top-level items)
order
integer
required
The sort order within the menu (lower numbers appear first)

Relationships

Belongs to relationship with the Menu model. Returns: BelongsTo<Menu>
$menuItem = MenuItem::find(1);
$menu = $menuItem->menu;

parent()

Belongs to relationship for the parent menu item. Returns: BelongsTo<MenuItem>
$menuItem = MenuItem::find(5);
$parent = $menuItem->parent; // null if top-level item

children()

Has many relationship for child menu items. Children are automatically ordered by their order field. Returns: HasMany<MenuItem>
$menuItem = MenuItem::find(1);
$children = $menuItem->children; // Ordered by 'order' column

// Check if item has children
if ($menuItem->children->count() > 0) {
    // Has submenu
}

Usage examples

Creating menu items

// Create top-level menu item
$homeItem = MenuItem::create([
    'menu_id' => 1,
    'label' => 'Home',
    'url' => '/',
    'parent_id' => null,
    'order' => 1
]);

// Create child menu item
$aboutTeamItem = MenuItem::create([
    'menu_id' => 1,
    'label' => 'Our Team',
    'url' => '/about/team',
    'parent_id' => $aboutItem->id,
    'order' => 1
]);

Building hierarchical menus

// Get all top-level items with children
$menuItems = MenuItem::where('menu_id', 1)
    ->whereNull('parent_id')
    ->with('children')
    ->orderBy('order')
    ->get();

// Recursive loading of all levels
$menuItems = MenuItem::where('menu_id', 1)
    ->whereNull('parent_id')
    ->with('children.children') // Load grandchildren
    ->orderBy('order')
    ->get();

Reordering menu items

// Update order for multiple items
$updates = [
    ['id' => 1, 'order' => 2],
    ['id' => 2, 'order' => 1],
    ['id' => 3, 'order' => 3]
];

foreach ($updates as $update) {
    MenuItem::where('id', $update['id'])
        ->update(['order' => $update['order']]);
}

Recursive menu rendering

<!-- Recursive Blade component: resources/views/components/menu-items.blade.php -->
@foreach($items as $item)
    <li>
        <a href="{{ $item->url }}" class="menu-link">
            {{ $item->label }}
        </a>
        
        @if($item->children->count() > 0)
            <ul class="submenu">
                <x-menu-items :items="$item->children" />
            </ul>
        @endif
    </li>
@endforeach
// Get breadcrumb trail for a menu item
function getBreadcrumbs(MenuItem $item): array
{
    $breadcrumbs = [$item];
    
    $current = $item;
    while ($current->parent) {
        $current = $current->parent;
        array_unshift($breadcrumbs, $current);
    }
    
    return $breadcrumbs;
}

$breadcrumbs = getBreadcrumbs(MenuItem::find(10));

Database schema

Based on migration 2025_05_25_175649_create_menu_items_table.php, the menu_items table contains:
  • id - Primary key
  • menu_id - Foreign key to menus table
  • label - Display text (string)
  • url - Link URL (string)
  • parent_id - Foreign key to menu_items (nullable)
  • order - Sort order (integer)
  • created_at - Timestamp
  • updated_at - Timestamp

Additional fields

You can extend the MenuItem model to include:
  • icon - Icon class or name
  • target - Link target (_self, _blank)
  • css_class - Custom CSS classes
  • active - Enable/disable menu item
  • permission - Required permission to view
When adding new fields, remember to update the $fillable array and create a migration.

Best practices

When deleting menu items with children, decide whether to also delete children or reassign them. Consider using database cascading deletes or a model observer.
Be careful with deeply nested menus (more than 3 levels) as they can be difficult to navigate on mobile devices.

Menu model

View Menu model documentation

Menu feature

Learn about the menu management feature

Build docs developers (and LLMs) love