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

Pd Menu Laravel Package

appaydin/pd-menu

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require appaydin/pd-menu
    
    • No manual bundle registration required in Symfony 4+ (auto-enabled).
  2. Create a Basic Menu Class Extend Pd\MenuBundle\Builder\Menu and override createMenu():

    // src/Menu/MyMenu.php
    namespace App\Menu;
    
    use Pd\MenuBundle\Builder\Menu;
    
    class MyMenu extends Menu {
        public function createMenu(array $options = []): ItemInterface {
            return $this->createRoot('my_menu')
                ->addChild('home', 1)
                    ->setRoute('home')
                    ->setLabel('Home');
        }
    }
    
  3. Render in Twig

    {{ pd_menu_render('App\Menu\MyMenu') }}
    

First Use Case

Dynamic Admin Sidebar

// src/Menu/AdminMenu.php
class AdminMenu extends Menu {
    public function createMenu(array $options = []): ItemInterface {
        $menu = $this->createRoot('admin_menu')
            ->setChildAttr(['class' => 'sidebar']);

        $menu->addChild('dashboard', 1)
            ->setRoute('admin_dashboard')
            ->setIcon('<i class="fas fa-tachometer-alt"></i>');

        $menu->addChild('users', 2)
            ->setRoute('admin_users')
            ->setRoles(['ROLE_ADMIN']);

        return $menu;
    }
}
{# templates/admin/base.html.twig #}
<div class="sidebar-menu">
    {{ pd_menu_render('App\Menu\AdminMenu', {
        'currentClass': 'active',
        'iconTemplate': '<i class="%icon%"></i>'
    }) }}
</div>

Implementation Patterns

Core Workflows

  1. Menu Hierarchy Construction

    // Nested menu with weights
    $menu = $this->createRoot('main_menu')
        ->addChild('products', 1)
            ->addChild('list', 1)
                ->setRoute('products_index')
            ->addChild('create', 2)
                ->setRoute('products_new')
        ->addChild('orders', 3)
            ->setRoute('orders_index');
    
  2. Dynamic Menu Items via Events

    // src/EventListener/DynamicMenuListener.php
    class DynamicMenuListener {
        public function onMenuBuild(PdMenuEvent $event) {
            if ($event->getMenuName() === 'admin_menu') {
                $event->getMenu()
                    ->addChild('notifications', 4)
                    ->setRoute('admin_notifications')
                    ->setBadgeCount($this->notificationService->unreadCount());
            }
        }
    }
    
    # config/services.yaml
    App\EventListener\DynamicMenuListener:
        tags:
            - { name: kernel.event_listener, event: admin_menu.event, method: onMenuBuild }
    
  3. Role-Based Visibility

    $menu->addChild('admin', 1)
        ->setRoute('admin_dashboard')
        ->setRoles(['ROLE_ADMIN', 'ROLE_SUPER_ADMIN']);
    
  4. Template Customization

    {# Custom template for dropdown menus #}
    {% extends '@PdMenu/Default/menu.html.twig' %}
    {% block menu_item %}
        <li class="dropdown">
            <a href="{{ item.route.path }}">{{ item.label }}</a>
            {% if item.children|length > 0 %}
                <ul class="dropdown-menu">
                    {% for child in item.children %}
                        <li>{{ pd_menu_render_child(child) }}</li>
                    {% endfor %}
                </ul>
            {% endif %}
        </li>
    {% endblock %}
    

Integration Tips

  1. Symfony Router Integration

    $menu->addChild('profile')
        ->setRoute('app_profile_show')
        ->setLinkAttr(['title' => 'User Profile']);
    
  2. Translation Support

    $menu->addChild('settings')
        ->setLabel('menu.settings') // Translatable key
        ->setTransDomain('admin');
    
    {{ pd_menu_render('App\Menu\AdminMenu', {'trans_domain': 'admin'}) }}
    
  3. Menu Caching

    # config/packages/pd_menu.yaml
    pd_menu:
        cache: true
        cache_lifetime: 3600
    
  4. Menu in Controllers

    public function index(MenuService $menuService) {
        $menu = $menuService->getMenu('main_menu');
        return $this->render('homepage.html.twig', ['menu' => $menu]);
    }
    

Gotchas and Tips

Common Pitfalls

  1. Event Naming

    • Events are auto-generated as {menu_class_name}.event (e.g., AdminMenu.event).
    • Fix: Verify event names match exactly (case-sensitive).
  2. Route Resolution

    • If routes fail, ensure:
      • The route exists in config/routes.yaml.
      • The route name matches exactly (e.g., 'admin_dashboard' vs 'admin/dashboard').
    • Debug: Use dump($menu->getItem('home')->getRoute()) to inspect.
  3. Child Parentage

    • addChildParent() requires the parent item to exist.
    • Fix: Chain methods properly:
      $menu->addChild('parent', 1)
          ->addChildParent('child', 2) // Correct
      
  4. Twig Template Paths

    • Custom templates must extend @PdMenu/Default/menu.html.twig.
    • Fix: Use absolute paths:
      {{ pd_menu_render('App\Menu\MyMenu', {'template': '@MyBundle/menu/custom.html.twig'}) }}
      

Debugging Tips

  1. Inspect Menu Structure

    $menu = $menuService->getMenu('main_menu');
    dump($menu->toArray()); // View raw structure
    
  2. Event Debugging

    public function onMenuBuild(PdMenuEvent $event) {
        dump($event->getMenuName(), $event->getOptions());
    }
    
  3. Template Debugging

    {{ dump(pd_menu_render('App\Menu\MyMenu', {'debug': true})) }}
    

Advanced Patterns

  1. Menu Factories

    // src/Service/MenuFactory.php
    class MenuFactory {
        public function createAdminMenu(): ItemInterface {
            return (new AdminMenu())->createMenu();
        }
    }
    
  2. Menu Versioning

    // src/Menu/AdminMenuV2.php
    class AdminMenuV2 extends Menu {
        public function createMenu(array $options = []): ItemInterface {
            // Updated structure
        }
    }
    
    {{ pd_menu_render('App\Menu\AdminMenuV2') }}
    
  3. Menu Data Providers

    // src/Service/UserMenuProvider.php
    class UserMenuProvider {
        public function getUserMenu(User $user): ItemInterface {
            $menu = (new UserMenu())->createMenu();
            $menu->addChild('profile')
                ->setRoute('user_profile', ['id' => $user->id]);
            return $menu;
        }
    }
    

Configuration Quirks

  1. Global vs. Local Overrides

    • Local template options override global config:
      {{ pd_menu_render('App\Menu\MyMenu', {'template': '@MyBundle/menu.html.twig'}) }}
      
    • Note: Global config in pd_menu.yaml only applies to default rendering.
  2. Depth Limitation

    • depth: null renders all levels.
    • depth: 1 renders only top-level items.
    • Use case: Limit nested menus in mobile views.
  3. Icon Template

    • Replace %icon% placeholder in iconTemplate:
      pd_menu:
          iconTemplate: '<i class="%icon% fa-fw"></i>'
      
  4. ArrayAccess Compatibility

    • Menus implement ArrayAccess, so you can use:
      $menu['home']->setActive(true);
      
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.
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope