Skip to content

Instantly share code, notes, and snippets.

@lsv
Last active January 11, 2020 10:40
Show Gist options
  • Save lsv/4d8044d21819f28f0dde52a3fb8211a0 to your computer and use it in GitHub Desktop.
Save lsv/4d8044d21819f28f0dde52a3fb8211a0 to your computer and use it in GitHub Desktop.
Symfony 4 - KnpMenuBundle - menu with event
<?php
// src/Menu/Menu.php
namespace App\Menu;
use App\Event\Menu\Topbar\UserMenuEvent;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class Menu
{
/**
* @var EventDispatcherInterface
*/
private $dispatcher;
/**
* @var FactoryInterface
*/
private $factory;
public function __construct(FactoryInterface $factory, EventDispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
$this->factory = $factory;
}
public function userTopbar(RequestStack $request): ItemInterface
{
$menu = $this->factory->createItem('root');
$this->dispatcher->dispatch(
UserMenuEvent::EVENT,
new UserMenuEvent($this->factory, $menu, $request)
);
return $menu;
}
}
// config/services.yaml
services:
app.menu_builder:
class: App\Menu\Menu
app.menu.usertopbar:
class: Knp\Menu\MenuItem
factory: ['@app.menu_builder', 'userTopbar']
tags:
- { name: knp_menu.menu, alias: userTopbar }
{# templates/topbar.htm.twig #}
{{ knp_menu_render('userTopbar') }}
<?php
// src/Event/Menu/Topbar.php
namespace App\Event\Menu\Topbar;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\RequestStack;
class UserMenuEvent extends Event
{
public const EVENT = 'app.menu.topbar.user';
/**
* @var FactoryInterface
*/
private $factory;
/**
* @var ItemInterface
*/
private $item;
/**
* @var RequestStack
*/
private $request;
public function __construct(FactoryInterface $factory, ItemInterface $item, RequestStack $request)
{
$this->factory = $factory;
$this->item = $item;
$this->request = $request;
}
/**
* @return FactoryInterface
*/
public function getFactory(): FactoryInterface
{
return $this->factory;
}
/**
* @return ItemInterface
*/
public function getItem(): ItemInterface
{
return $this->item;
}
/**
* @return RequestStack
*/
public function getRequest(): RequestStack
{
return $this->request;
}
}
<?php
// src/Subscriber/UserMenuSubscriber.php
namespace App\Subscriber;
use App\Entity\User;
use App\Event\Menu\Topbar\UserMenuEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Translation\TranslatorInterface;
class UserMenuSubscriber implements EventSubscriberInterface
{
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var TranslatorInterface
*/
private $translator;
public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
{
$this->tokenStorage = $tokenStorage;
$this->translator = $translator;
}
public function onUserMenuConfigure(UserMenuEvent $event)
{
$menu = $event->getItem();
/** @var User $user */
$user = $this->tokenStorage->getToken()->getUser();
$dropdown = $menu->addChild(
$this->translator->trans('Hello %username%', ['%username%' => $user->getUsername()], 'usermenu'),
['dropdown' => true]
);
$dropdown->addChild(
$this->translator->trans('Profile', [], 'usermenu'),
['route' => 'profile_index']
);
}
public static function getSubscribedEvents(): array
{
return [
UserMenuEvent::EVENT => 'onUserMenuConfigure',
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment