Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Knp Menu Bundle Laravel Package

knplabs/knp-menu-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require knplabs/knp-menu-bundle
    

    Ensure the bundle is enabled in config/bundles.php:

    Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true],
    
  2. First Menu Creation: Create a menu builder service (e.g., src/Menu/Builder.php):

    use Knp\Menu\FactoryInterface;
    use Knp\Menu\MenuItem;
    
    class Builder
    {
        public function __construct(private FactoryInterface $factory)
        {
        }
    
        public function createMainMenu(): MenuItem
        {
            $menu = $this->factory->createItem('root');
            $menu->addChild('Home', ['route' => 'home']);
            $menu->addChild('About', ['route' => 'about']);
            return $menu;
        }
    }
    
  3. Register the Builder: Add to services.yaml:

    services:
        App\Menu\Builder:
            arguments:
                $factory: '@knp_menu.factory'
    
  4. Render in Twig:

    {{ knp_menu_render('main', {'menu': app.menu_builder.createMainMenu()}) }}
    

First Use Case: Dynamic Navigation

Use the matcher and provider services to auto-generate menus from routes or entities:

# config/packages/knp_menu.yaml
knp_menu:
    matcher: ~ # Auto-match routes
    provider: ~ # Auto-provide items from routes

Render in Twig:

{{ knp_menu_render('main') }}

Implementation Patterns

Menu Builders

  1. Service-Based Builders: Create reusable builders for different menu types (e.g., HeaderMenu, FooterMenu). Inject dependencies like Router, Security, or Doctrine for dynamic logic:

    public function __construct(
        private FactoryInterface $factory,
        private RouterInterface $router,
        private Security $security
    ) {}
    
    public function createAdminMenu(): MenuItem
    {
        $menu = $this->factory->createItem('admin');
        if ($this->security->isGranted('ROLE_ADMIN')) {
            $menu->addChild('Dashboard', ['route' => 'admin_dashboard']);
        }
        return $menu;
    }
    
  2. Event-Driven Menus: Use Symfony events (e.g., KernelEvents::REQUEST) to dynamically update menus:

    public function onKernelRequest(GetResponseEvent $event)
    {
        $menu = $this->factory->createItem('root');
        $menu->addChild('Current User', ['route' => 'profile']);
        $this->menuBuilder->setMenu('main', $menu);
    }
    

Twig Integration

  • Named Menus: Pass named menus to Twig for reuse:

    $menu = $this->menuBuilder->createMainMenu();
    return $this->render('home.html.twig', ['menu' => $menu]);
    
    {{ knp_menu_render('menu', {'menu': menu}) }}
    
  • Menu Theming: Override default Twig templates in templates/KnpMenu/:

    {# templates/KnpMenu/menu.html.twig #}
    <nav>
        <ul>
            {% for item in root.children %}
                <li>{{ item.label }}
                    {% if item.children|length > 0 %}
                        {{ knp_menu_render('item', {'menu': item}) }}
                    {% endif %}
                </li>
            {% endfor %}
        </ul>
    </nav>
    

Advanced Features

  1. Route Matching: Use the matcher to auto-generate menus from routes:

    knp_menu:
        matcher:
            class: Knp\Menu\Matcher\RouteMatcher
            options:
                routes: ['home', 'about', 'contact']
    
  2. Entity Providers: Fetch menu items from Doctrine entities:

    knp_menu:
        provider:
            class: Knp\Menu\Provider\EntityProvider
            options:
                entity: App\Entity\MenuItem
                property: path
    
  3. Caching: Cache menus for performance:

    knp_menu:
        cache:
            class: Knp\Menu\Cache\SymfonyCache
            options:
                namespace: knp_menu
    

Gotchas and Tips

Common Pitfalls

  1. Circular References: Avoid circular references in menu items (e.g., A -> B -> A). KnpMenu throws a CircularReferenceException.

  2. Matcher Conflicts: If using both RouteMatcher and UriMatcher, ensure routes/URIs are unique to avoid duplicate items.

  3. Twig Rendering Issues: Ensure the KnpMenuBundle Twig extension is loaded. If not, manually register it:

    // config/packages/twig.yaml
    twig:
        globals:
            knp_menu_renderer: '@knp_menu.renderer.twig_extension'
    
  4. Security Context: Always check permissions in builders or use the Security component to avoid exposing sensitive menu items:

    if (!$this->security->isGranted('ROLE_USER')) {
        $menu->removeChild('profile');
    }
    

Debugging

  1. Dump Menu Structure: Use var_dump($menu->getChildren()) or Knp\Menu\Renderer\TwigRenderer::dump($menu) to inspect the menu tree.

  2. Enable Debug Mode: Set debug: true in knp_menu.yaml to log menu generation:

    knp_menu:
        debug: true
    
  3. Check Cache: Clear the cache if menus aren’t updating:

    php bin/console cache:clear
    

Extension Points

  1. Custom Matchers: Extend Knp\Menu\Matcher\MatcherInterface to match items against custom logic (e.g., database flags):

    class CustomMatcher implements MatcherInterface
    {
        public function match(MenuItem $item, array $options)
        {
            // Custom logic here
            return $item->getUri() === $options['expected_uri'];
        }
    }
    
  2. Dynamic Child Addition: Use addCallback to dynamically add children:

    $menu->addChild('Dynamic', ['route' => 'dynamic'])
         ->setAttribute('callback', function (MenuItem $item) {
             $item->addChild('Subitem', ['route' => 'subitem']);
         });
    
  3. Menu Events: Listen to Knp\Menu\Event\MenuEvent to modify menus globally:

    use Knp\Menu\Event\MenuEvent;
    
    $eventDispatcher->addListener(MenuEvent::PRE_BUILD, function (MenuEvent $event) {
        $event->setMenu($event->getMenu()->addChild('Global Item', ['route' => 'global']));
    });
    

Configuration Quirks

  1. Provider vs. Matcher:

    • Use provider to generate menu items (e.g., from routes/entities).
    • Use matcher to filter existing items (e.g., highlight active routes).
  2. Priority Order: Matchers run in the order defined in knp_menu.yaml. Later matchers override earlier ones.

  3. Twig Renderer Options: Pass options to knp_menu_render for customization:

    {{ knp_menu_render('main', {
        'template': 'KnpMenu/menu.html.twig',
        'depth': 2,
        'currentUri': app.request.getUri()
    }) }}
    
  4. Symfony 6+ Changes: If using Symfony 6+, ensure knp_menu.yaml is in config/packages/ and not config/knp_menu.yaml (deprecated).

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware