我正在制作一个管理菜单包。我希望其他包能够将菜单项添加到包中,但我也希望在删除包时删除菜单项。最好的方法是什么?
我可以创建一个“重新生成管理菜单”操作,扫描所有捆绑包中的某个 YML,然后将其存储在缓存或数据库中。
有一个更好的方法吗 ?
您可以使用标签从其他捆绑包(甚至相同)中查找服务,并使用它们在compiler pass中从它们构建菜单。
在本例中,我假设您将菜单定义为服务(我将使用 service id acme_menu.menu
)。
// src/Acme/MenuBundle/DependencyInjection/Compiler/BuildMenuCompilerPass.php
namespace Acme\MenuBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
class BuildMenuCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('acme_menu.menu')) {
return;
}
$definition = $container->getDefinition('acme_menu.menu');
$taggedServices = $container->findTaggedServiceIds('acme_menu.item');
foreach ($taggedServices as $id => $attributes) {
$definition->addMethodCall(
'addMenuItem',
array(new Reference($id))
);
}
}
}
将其注册到您的菜单包中:
// src/Acme/MenuBundle/AcmeMenuBundle.php
namespace Acme\MenuBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Acme\MenuBundle\DependencyInjection\Compiler\BuildMenuCompilerPass;
class AcmeMenuBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new BuildMenuCompilerPass());
}
}
并且每个标记为的服务acme_menu.item
都将被添加到菜单中——它们的方法addMenuItem
将在菜单上被调用,并以标记的服务作为参数。所以简单定义:
# services.yml
services:
acme_demo.menu.item1:
# ...
tags:
- { name: acme_menu.item }
acme_demo.menu.item2:
# ...
tags:
- { name: acme_menu.item }