c33s/menu-bundle
Routing-based menu system for Symfony2. MenuBundle builds navigation menus from your routing configuration, helping you keep menu structure in sync with routes and simplify link management across your application.
Installation
composer require c33s/menu-bundle
Add to config/bundles.php:
return [
// ...
C33S\MenuBundle\C33SMenuBundle::class => ['all' => true],
];
Basic Configuration
Create a YAML menu definition in config/menus.yml:
main:
items:
home:
label: 'Home'
route: 'homepage'
about:
label: 'About'
route: 'about'
First Usage In a Twig template:
{{ menu('main') }}
Or in a controller:
return $this->render('template.html.twig', [
'menu' => $this->get('c33s_menu.menu_builder')->build('main'),
]);
Key Files to Review
config/menus.yml (default config location)src/C33S/MenuBundle/Builder/MenuBuilder.php (core logic)Resources/views/Menu/menu.html.twig (default Twig template)Dynamic Menu Building
Use the MenuBuilder service to programmatically construct menus:
$menu = $this->get('c33s_menu.menu_builder')
->build('main')
->addChild('contact', [
'label' => 'Contact',
'route' => 'contact',
]);
Route-Based Menus Leverage Symfony’s routing system for automatic active state:
admin:
items:
dashboard:
label: 'Dashboard'
route: 'admin_dashboard'
active: 'equals' # Checks if current route matches
Nested Menus Define hierarchical menus in YAML:
navigation:
items:
products:
label: 'Products'
route: 'products_index'
children:
electronics:
label: 'Electronics'
route: 'products_electronics'
Twig Integration Use Twig extensions for flexible rendering:
{% for item in menu('main').children %}
<li class="{{ item.isActive ? 'active' }}">
<a href="{{ path(item.route) }}">{{ item.label }}</a>
</li>
{% endfor %}
Event-Driven Customization
Subscribe to c33s_menu.menu_builder.build event to modify menus:
// In a service
public function onBuildMenu(MenuEvent $event) {
$menu = $event->getMenu();
$menu->addChild('custom_item', ['label' => 'Dynamic Item']);
}
Cache Optimization
Enable caching in config.yml:
c33s_menu:
cache: true
cache_lifetime: 3600
Symfony Flex Compatibility
If using Symfony Flex, place menu configs in config/packages/c33s_menu.yaml:
c33s_menu:
menus:
main:
items:
home: { label: 'Home', route: 'home' }
Dependency Injection
Inject MenuBuilder directly into services:
public function __construct(MenuBuilder $menuBuilder) {
$this->menuBuilder = $menuBuilder;
}
Active State Logic
Customize active state checks via active option:
items:
blog:
label: 'Blog'
route: 'blog_index'
active: 'contains' # Checks if current route contains 'blog'
Translation Support
Use Twig’s trans filter for labels:
items:
home:
label: 'menu.home' # Translatable key
route: 'home'
{{ item.label|trans }}
Security Integration Combine with Symfony’s security component:
items:
admin:
label: 'Admin'
route: 'admin'
access_control: 'ROLE_ADMIN'
Route Name Mismatches
php bin/console debug:router.path() in Twig to auto-generate URLs:
<a href="{{ path(item.route) }}">{{ item.label }}</a>
Caching Headaches
menus.yml.php bin/console cache:clear
c33s_menu:
cache: '%kernel.debug%'
Active State Logic Errors
active option not working as expected.equals: Exact route match.contains: Route contains the item’s route.regex: Custom regex match.{{ dump(item.isActive) }}
YAML Parsing Quirks
Event Subscriber Conflicts
tags:
- { name: kernel.event_listener, event: c33s_menu.menu_builder.build, method: onBuildMenu, priority: 100 }
Dump Menu Structure
{{ dump(menu('main')) }}
Or in PHP:
var_dump($menu->toArray());
Check Event Dispatch Enable debug mode to see fired events:
php bin/console debug:event-dispatcher
Override Default Twig Template
Copy vendor/c33s/menu-bundle/Resources/views/Menu/menu.html.twig to templates/Menu/menu.html.twig for customization.
Custom Menu Builders
Extend MenuBuilder to add logic:
class CustomMenuBuilder extends MenuBuilder {
public function build($name) {
$menu = parent::build($name);
// Add custom logic
return $menu;
}
}
Register as a service:
services:
c33s_menu.menu_builder.custom:
class: App\Menu\CustomMenuBuilder
tags: ['c33s_menu.menu_builder']
Dynamic Menu Items
Use MenuItem class to create items programmatically:
$item = new MenuItem('dynamic_item', [
'label' => 'Dynamic Item',
'route' => 'dynamic_route',
]);
$menu->addChild($item);
Custom Active State Providers
Implement C33S\MenuBundle\Provider\ActiveStateProviderInterface for custom logic:
class CustomActiveStateProvider implements ActiveStateProviderInterface {
public function isActive(MenuItem $item, Request $request) {
// Custom logic
return $request->get('_route') === 'custom_route';
}
}
Register in config:
c33s_menu:
active_state_provider: 'app.custom_active_state_provider'
Menu Item Classes
Extend MenuItem for custom properties:
class ExtendedMenuItem extends MenuItem {
protected $extraData;
public function setExtraData($data) {
$this->extraData = $data;
}
}
Use in YAML:
items:
custom:
class: App\Menu\ExtendedMenuItem
extra_data: { key: 'value' }
How can I help you explore Laravel packages today?