Symfony4中使用KnpMenuBundle遇报错,寻求MenuBuilder使用方案
嘿,我来帮你搞定这个问题!你遇到的坑其实是Symfony4的无Bundle结构和KnpMenuBundle旧调用逻辑不匹配导致的,下面一步步给你捋清楚怎么解决:
1. 先搞懂为啥报错
你第一次用{{ knp_menu_render('App:MenuBuilder:menuTags') }}时出现的Bundle不存在错误,是因为这个语法是给传统Symfony Bundle项目用的(格式是BundleName:Class:method),但Symfony4默认已经没有AppBundle了,框架自然找不到对应的Bundle,所以直接报错。
2. 正确的服务调用方式
你尝试用App\Menu\Builder:menuTags不对,KnpMenuBundle对服务形式的调用有特定格式,这里给你两种靠谱的方法:
方法一:直接用全限定服务ID调用
Symfony4会自动把你的MenuBuilder注册成服务,默认服务ID就是类的全限定名App\Menu\MenuBuilder。调用时要写成@服务ID::方法名的格式:
{{ knp_menu_render('@App\\Menu\\MenuBuilder::menuTags') }}
或者用单引号包裹,这样反斜杠不用转义:
{{ knp_menu_render('@App\Menu\MenuBuilder::menuTags') }}
方法二:给菜单配置别名(更清爽)
如果觉得全限定名太长,你可以在config/services.yaml里给这个菜单方法配个别名,以后调用就简单多了:
services: # 其他服务配置保持不变 App\Menu\MenuBuilder: tags: - { name: knp_menu.menu_builder, method: menuTags, alias: tags_menu }
配置好之后,直接用别名就能渲染菜单:
{{ knp_menu_render('tags_menu') }}
3. 确认你的MenuBuilder类没问题
顺便检查下你的MenuBuilder是不是写对了,要记得注入FactoryInterface,给你个示例参考:
<?php namespace App\Menu; use Knp\Menu\FactoryInterface; use Symfony\Component\HttpFoundation\RequestStack; class MenuBuilder { private $factory; private $requestStack; public function __construct(FactoryInterface $factory, RequestStack $requestStack) { $this->factory = $factory; $this->requestStack = $requestStack; } public function menuTags(array $options) { $menu = $this->factory->createItem('root'); // 这里添加你的菜单项,比如: $menu->addChild('标签列表', ['route' => 'tag_index']); $menu->addChild('新建标签', ['route' => 'tag_new']); return $menu; } }
4. 最后验证一下
你说这个服务能注入到控制器,说明服务注册是正常的,只要调用格式对了,菜单就能正常渲染出来。
说白了就是Symfony4没了传统Bundle,所以得用服务的方式来调用KnpMenu的菜单方法,别再用旧的Bundle语法啦~
内容的提问来源于stack exchange,提问作者Developer

