Installation
composer require disjfa/menu-bundle
Add to config/bundles.php (Symfony):
return [
// ...
Disjfa\MenuBundle\DisjfaMenuBundle::class => ['all' => true],
];
Publish Configuration
php artisan vendor:publish --provider="Disjfa\MenuBundle\DisjfaMenuBundle" --tag="config"
This creates config/menu.php with default settings for site_menu and admin_menu.
First Use Case: Basic Site Menu
Define a menu in config/menu.php:
'site_menu' => [
'items' => [
['label' => 'Home', 'route' => 'home'],
['label' => 'About', 'route' => 'about'],
],
],
Render in a Twig template:
{{ render(knp_menu('site_menu')) }}
YAML Configuration (Recommended)
Use config/menu.yaml for maintainability:
site_menu:
items:
- label: "Products"
route: "products.index"
children:
- label: "Category 1"
route: "products.category1"
Dynamic Menu Building Extend the builder via a service:
// src/Service/CustomMenuBuilder.php
class CustomMenuBuilder extends AbstractMenuBuilder
{
public function buildSiteMenu(): MenuNode
{
$menu = $this->factory->createItem('root');
$menu->addChild('Dynamic Item', ['route' => 'dynamic_route']);
return $menu;
}
}
Register in services.yaml:
services:
App\Service\CustomMenuBuilder:
tags: [disjfa.menu.builder]
Integration with Authentication Conditionally render items based on user roles:
// In a Twig extension or controller
$menu = $this->menuBuilder->buildSiteMenu();
if (!$this->auth->isGranted('ROLE_ADMIN')) {
$menu->removeChild('Admin Panel');
}
Admin Panel Menus
Use admin_menu for backend navigation with nested CRUD routes:
'admin_menu' => [
'items' => [
['label' => 'Users', 'route' => 'admin.users.index', 'icon' => 'fas fa-users'],
['label' => 'Settings', 'route' => 'admin.settings.index', 'children' => [...]],
],
],
Multi-Language Menus
Override menu items per locale in config/menu_{locale}.php:
'site_menu' => [
'items' => [
['label' => 'Accueil', 'route' => 'home'], // French
],
],
Active Menu Highlighting
Use Twig’s is_active filter:
<li class="{{ path('current_route') == 'home' ? 'active' : '' }}">
{{ knp_menu_item('site_menu', 'Home') }}
</li>
Caching Issues
php artisan cache:clear
config/menu.php for development:
'cache' => false,
Route Name Conflicts
/home) as fallbacks:
['label' => 'Home', 'uri' => '/home'],
KnpMenuBundle Dependency
KnpMenuBundle. Install if missing:
composer require knplabs/knp-menu-bundle
Twig Rendering Quirks
render() for full menus, knp_menu_item() for single items:
{# Correct #}
{{ render(knp_menu('site_menu')) }}
{# Incorrect (throws error) #}
{{ knp_menu('site_menu') }}
Dump Menu Structure Add to a controller to inspect the menu tree:
dd($this->menuBuilder->buildSiteMenu()->getChildren());
Check Builder Priority
If custom builders aren’t triggered, verify they’re tagged in services.yaml:
tags: [disjfa.menu.builder] # Must match exactly
Custom Menu Factories
Override the default KnpMenuFactory by binding a new service:
// config/services.php
Disjfa\MenuBundle\Menu\MenuFactoryInterface::class => App\Menu\CustomFactory::class,
Event Listeners Listen for menu build events to modify items dynamically:
// src/EventListener/MenuListener.php
class MenuListener
{
public function onMenuBuild(MenuBuildEvent $event)
{
$event->getMenu()->addChild('Dynamic Item', ['route' => 'dynamic']);
}
}
Register in events.yaml:
Disjfa\MenuBundle\Event\MenuBuildEvent: ['listener' => App\EventListener\MenuListener]
Database-Backed Menus Fetch menu items from a database and merge with config:
// In a custom builder
$dbItems = $this->menuRepository->findAll();
$menu = $this->factory->createItem('root');
foreach ($dbItems as $item) {
$menu->addChild($item['label'], ['route' => $item['route']]);
}
How can I help you explore Laravel packages today?