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

Menu Bundle Laravel Package

dama/menu-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require dama/menu-bundle
    

    Add to config/app.php under providers:

    Dama\DamaMenuBundle\DamaMenuBundle::class,
    
  2. First Use Case: Basic Menu Create a MenuTreeBuilder class (e.g., src/Menu/MainMenuTreeBuilder.php) implementing MenuTreeBuilderInterface:

    use Dama\DamaMenuBundle\Menu\MenuTreeBuilderInterface;
    use Dama\DamaMenuBundle\Menu\Node;
    
    class MainMenuTreeBuilder implements MenuTreeBuilderInterface
    {
        public function buildTree(Node $root): void
        {
            $root
                ->child('Dashboard')
                ->setRoute('dashboard');
        }
    }
    
  3. Register the Builder In config/packages/dama_menu.yaml (create if missing):

    menu_builder: App\Menu\MainMenuTreeBuilder
    
  4. Render in Twig

    {{ dump(app.dama_menu.render('main_menu')) }}
    

Implementation Patterns

Core Workflow: Dynamic Menu Construction

  1. Hierarchical Node Building Use fluent methods (child(), end()) to define nested menus:

    $root
        ->child('Admin')
            ->setRoute('admin_dashboard')
            ->child('Users')
                ->setRoute('admin_users_list')
            ->end()
        ->end();
    
  2. Permission-Based Visibility Restrict nodes with setRequiredPermissions():

    ->setRequiredPermissions(['ROLE_ADMIN', 'ROLE_SUPER_ADMIN'])
    
  3. Active State Logic Use setAdditionalActiveRequestMatcher() for custom active state checks:

    ->setAdditionalActiveRequestMatcher(function (Request $request) {
        return $request->query->has('active_tab');
    })
    
  4. Conditional Rendering Dynamically add nodes with ifTrue():

    ->ifTrue($this->isFeatureEnabled('analytics'))
        ->child('Analytics')
            ->setRoute('analytics_dashboard')
        ->end();
    

Integration Tips

  • Twig Integration Access the menu in templates via app.dama_menu.render('menu_name'). Customize output with Twig filters (e.g., {{ menu|dama_menu_render }}).

  • Symfony Security Integration Use ExpressionLanguage for complex permission checks:

    ->setRequiredPermissions([new Expression("has_role('ROLE_USER') and not has_role('ROLE_GUEST')")])
    
  • Caching Enable caching in config/packages/dama_menu.yaml:

    cache: true
    cache_lifetime: 3600
    
  • Multi-Language Support Localize labels via translation keys:

    ->child('{{ 'menu.dashboard'|trans }}')
    

Gotchas and Tips

Pitfalls

  1. Permission Evaluation Order

    • Permissions are evaluated depth-first. A parent node’s permissions hide all children, even if they have unique permissions.
    • Fix: Use setRequiredPermissions([]) on parent nodes if children should override visibility.
  2. Route Resolution

    • Routes must exist in Symfony’s router. Undefined routes throw RouteNotFoundException.
    • Debug: Use app.dama_menu.getMenu('menu_name')->getRoot()->getChildren() to inspect the tree.
  3. Circular References

    • Avoid recursive ifTrue() conditions that rebuild the tree infinitely.
    • Fix: Use static flags or external state management.
  4. Twig Context

    • The Request object in ActiveRequestMatcher is not the current Twig request. Use RequestStack for context-aware checks:
      use Symfony\Component\HttpFoundation\RequestStack;
      $requestStack = $this->container->get('request_stack');
      $request = $requestStack->getCurrentRequest();
      

Debugging Tips

  • Dump the Menu Tree
    $menu = app('dama_menu')->getMenu('main_menu');
    dump($menu->getRoot()->getChildren());
    
  • Check Permissions Use Symfony’s AuthorizationChecker to verify user roles:
    $this->authorizationChecker->enough($user, ['ROLE_ADMIN']);
    
  • Log Active States Override ActiveRequestMatcher to log conditions:
    ->setAdditionalActiveRequestMatcher(function (Request $request) {
        \Log::debug('Checking active state for:', ['path' => $request->getPathInfo()]);
        return str_starts_with($request->path(), '/debug');
    });
    

Extension Points

  1. Custom Node Types Extend Node to add metadata:

    class CustomNode extends Node
    {
        public function setBadge(string $badge): self { ... }
    }
    
  2. Event Listeners Subscribe to MenuBuilderEvent to modify menus dynamically:

    use Dama\DamaMenuBundle\Event\MenuBuilderEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class MenuSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents(): array
        {
            return [MenuBuilderEvent::class => 'onMenuBuild'];
        }
    
        public function onMenuBuild(MenuBuilderEvent $event): void
        {
            $event->getMenu()->getRoot()->addChild('Dynamic Node');
        }
    }
    
  3. Override Twig Rendering Create a custom Twig extension to modify output:

    class CustomMenuExtension extends \Twig\Extension\AbstractExtension
    {
        public function getFilters(): array
        {
            return [
                new \Twig\TwigFilter('custom_menu_render', [$this, 'renderMenu']),
            ];
        }
    
        public function renderMenu(array $menu): string
        {
            // Custom logic here
            return '<ul>' . implode('', $menu) . '</ul>';
        }
    }
    
  4. Database-Backed Menus Fetch menu structure from a DB and hydrate nodes:

    $menuItems = $this->menuRepository->findAll();
    foreach ($menuItems as $item) {
        $root->child($item->label)
            ->setRoute($item->route)
            ->setRequiredPermissions($item->permissions);
    }
    
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.
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky