Installation Add the package via Composer (if still needed for legacy projects):
composer require 21torr/menu
Publish the config (if available):
php artisan vendor:publish --provider="21TORR\MenuBundle\MenuServiceProvider"
Basic Usage
Register a menu in a service provider (e.g., AppServiceProvider):
use Symfony\Component\HttpKernel\Bundle\Bundle;
use 21TORR\MenuBundle\Menu\MenuInterface;
public function boot()
{
$this->app->bind('menu.main', function ($app) {
return $this->app->makeWith('21TORR\MenuBundle\Menu\Menu', [
'name' => 'main',
'items' => [
['label' => 'Home', 'route' => 'home'],
['label' => 'About', 'route' => 'about'],
],
]);
});
}
First Render Inject the menu into a controller or view:
public function index(MenuInterface $menu)
{
return view('home', ['menu' => $menu->get('main')]);
}
Dynamic Menu Generation Use closures to fetch menu items dynamically (e.g., from a database):
$this->app->bind('menu.admin', function ($app) {
return $this->app->makeWith('21TORR\MenuBundle\Menu\Menu', [
'name' => 'admin',
'items' => function () use ($app) {
return $app['db']->select('SELECT * FROM menu_items WHERE user_id = ?', [auth()->id()]);
},
]);
});
Nested Menus Support hierarchical menus via recursive item definitions:
'items' => [
[
'label' => 'Products',
'route' => 'products.index',
'children' => [
['label' => 'Category 1', 'route' => 'products.category1'],
],
],
],
View Integration Render menus in Blade templates:
@foreach($menu->get('main') as $item)
<li>
<a href="{{ route($item['route']) }}">{{ $item['label'] }}</a>
@if(isset($item['children']))
<ul>
@include('partials.menu', ['items' => $item['children']])
</ul>
@endif
</li>
@endforeach
Active Item Highlighting Add logic to highlight the current route:
'items' => array_map(function ($item) {
$item['active'] = request()->routeIs($item['route']);
return $item;
}, $originalItems),
Archived Status
spatie/laravel-menu or orchid/menu.Lack of Documentation
Menu, MenuInterface, MenuItem.Service Provider Binding
No Built-in Caching
$menu = Cache::remember("menu.{$userId}", now()->addHours(1), function () use ($userId) {
return $this->app->make('menu.admin');
});
Check Bindings Dump registered menus:
dd($this->app->bound('menu.*')); // Check if menus are bound
dd($this->app->make('menu.main')); // Inspect a menu instance
Validate Item Structure
Ensure items are arrays with label and route keys. Missing keys may cause silent failures.
Route Resolution Debug route generation:
dd(route($item['route'])); // Verify route exists
Custom Menu Items
Extend MenuItem to add metadata (e.g., icons, permissions):
class ExtendedMenuItem extends MenuItem
{
public $icon;
public $requiresPermission;
}
Menu Builders Create a fluent interface for menu construction:
class MenuBuilder
{
public function addItem(string $label, string $route): self
{
$this->items[] = compact('label', 'route');
return $this;
}
}
Event Listeners
Trigger events for menu rendering (e.g., MenuRendering):
event(new MenuRendering($menuName, $items));
How can I help you explore Laravel packages today?