使用事件扩展菜单
如果您想让系统的不同部分钩入菜单的构建过程,一个好的方法是使用基于 Symfony EventDispatcher 组件的方法。
创建菜单构建器
您的菜单构建器将创建基本菜单项,然后分发一个事件,以允许应用程序的其他部分向其添加更多内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// src/Menu/MainBuilder.php
namespace App\Menu;
use App\Event\ConfigureMenuEvent;
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class MainBuilder implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function build(FactoryInterface $factory)
{
$menu = $factory->createItem('root');
$menu->addChild('Dashboard', ['route' => '_acp_dashboard']);
$this->container->get('event_dispatcher')->dispatch(
new ConfigureMenuEvent($factory, $menu),
ConfigureMenuEvent::CONFIGURE
);
return $menu;
}
}
注意
此实现假定您使用 BuilderAliasProvider
(将您的菜单作为 App:MainBuilder:build
) 获取,但您也可以将其定义为服务并注入 event_dispatcher
服务作为依赖项。
创建事件对象
事件对象允许将一些数据传递给监听器。在本例中,它将保存正在创建的菜单和工厂。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
// src/Event/ConfigureMenuEvent.php
namespace App\Event;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Symfony\Component\EventDispatcher\Event;
class ConfigureMenuEvent extends Event
{
const CONFIGURE = 'app.menu_configure';
private $factory;
private $menu;
public function __construct(FactoryInterface $factory, ItemInterface $menu)
{
$this->factory = $factory;
$this->menu = $menu;
}
/**
* @return \Knp\Menu\FactoryInterface
*/
public function getFactory()
{
return $this->factory;
}
/**
* @return \Knp\Menu\ItemInterface
*/
public function getMenu()
{
return $this->menu;
}
}
就是这样。您的构建器现在提供了一个钩子。让我们看看如何使用它!
创建监听器
您可以为事件注册任意数量的监听器。让我们添加一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// src/Acme/AdminBundle/EventListener/ConfigureMenuListener.php
namespace Acme\AdminBundle\EventListener;
use App\Event\ConfigureMenuEvent;
class ConfigureMenuListener
{
public function __invoke(ConfigureMenuEvent $event)
{
$menu = $event->getMenu();
$menu->addChild('Matches', ['route' => 'versus_rankedmatch_acp_matches_index']);
$menu->addChild('Participants', ['route' => 'versus_rankedmatch_acp_participants_index']);
}
}
您现在可以注册监听器。
1 2 3 4 5
# config/services.yaml
services:
app.admin_configure_menu_listener:
class: Acme\AdminBundle\EventListener\ConfigureMenuListener
tags: [kernel.event_listener]
您还可以将您的监听器创建为订阅者,并使用 kernel.event_subscriber
标签,该标签没有任何附加属性。
这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可获得许可。