跳到内容

使用事件扩展菜单

编辑此页

如果您想让系统的不同部分钩入菜单的构建过程,一个好的方法是使用基于 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 许可获得许可。
目录
    版本