如何删除 Symfony 服务? (奏鸣曲分类)
How to remove a Symfony service? (Sonata Classification)
我将 SonataAdminBundle 与依赖于 ClassificationBundle 的 MediaBundle 一起使用。默认情况下,ClassificationBundle 添加了类别、标签、集合和上下文的后端管理管理,但由于我的应用程序不使用它们,我想从菜单和管理面板中删除它们。
我以前从未删除过服务,所以我不知道该怎么做。
必须有一种方法可以从 SonataClassificationBundle/Resources/config/admin.xml
中删除这些服务,显然不需要修改文件本身,因为它是供应商文件。
<services>
<service id="sonata.classification.admin.category" class="%sonata.classification.admin.category.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_categories" label_catalogue="%sonata.classification.admin.category.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.category.entity%</argument>
<argument>%sonata.classification.admin.category.controller%</argument>
<argument type="service" id="sonata.classification.manager.context" />
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.category.translation_domain%</argument>
</call>
<call method="setTemplates">
<argument type="collection">
<argument key="list">SonataClassificationBundle:CategoryAdmin:list.html.twig</argument>
</argument>
</call>
</service>
<service id="sonata.classification.admin.tag" class="%sonata.classification.admin.tag.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_tags" label_catalogue="%sonata.classification.admin.tag.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.tag.entity%</argument>
<argument>%sonata.classification.admin.tag.controller%</argument>
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.tag.translation_domain%</argument>
</call>
</service>
<service id="sonata.classification.admin.collection" class="%sonata.classification.admin.collection.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_collections" label_catalogue="%sonata.classification.admin.collection.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.collection.entity%</argument>
<argument>%sonata.classification.admin.collection.controller%</argument>
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.collection.translation_domain%</argument>
</call>
</service>
<service id="sonata.classification.admin.context" class="%sonata.classification.admin.context.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_contexts" label_catalogue="%sonata.classification.admin.context.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.context.entity%</argument>
<argument>%sonata.classification.admin.context.controller%</argument>
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.context.translation_domain%</argument>
</call>
</service>
</services>
或者是否有办法将它们从 Sonata 管理池中删除?因为它们被标记为 sonata.admin
?
编辑
使用 Sonata Easy Extends 我已经扩展了包并添加了一个 Compiler Pass:
class ApplicationSonataClassificationBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'SonataClassificationBundle';
}
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new CustomCompilerPass());
}
}
编译过程看起来像这样
class CustomCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$container->removeDefinition('sonata.classification.admin.category');
}
}
但我得到
You have requested a non-existent service "sonata.classification.admin.cate
gory" in . (which is being imported from "E:\svn\parkresort\app/config\rout
ing/sonata.yml").
该文件正在导入整个奏鸣曲包的路由
admin:
resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml'
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin
#sonata media
media:
resource: '@SonataMediaBundle/Resources/config/routing/media.xml'
prefix: /media
我猜即使从容器中删除后,奏鸣曲管理员仍在使用该服务。我该如何改变它?
EDIT2
我做到了!我必须将 Compiler Pass 放在 Sonata Admin Extension(及其命名空间)中,而不是放在 Sonata Media 中。显然,还扩展了管理包。之后工作得很好。
我不太明白为什么在我的扩展包之后加载原始包时它会起作用:
//AppKernel.php
new ApplicationSonataAdminBundle(),//extended
new Sonata\AdminBundle\SonataAdminBundle(),
真奇怪。
由于我们讨论的是依赖于您的应用程序的捆绑包,因此您无法控制它定义和注册到您的应用程序中的服务。
我相信可以使用 ContainerBuilder::removeDefinition() 删除它们。它也适用于其他包中定义的服务,因此它适用于 Sonata 包。
您可以在 Symfony's documentation 中查看有关将此代码放置在何处以及如何访问 ContainerBuilder
对象的示例。
但是,我建议你不要这样做。即使您不会使用某些服务,它们也不会打扰您,而且考虑到 Symfony 处理服务的方式,它们不会在生产中造成任何性能问题,我保证。
您将需要创建编译器传递以删除定义。
为了能够做到这一点,您必须确保您的捆绑包是在奏鸣曲之后声明的。如果您无法控制它,那么 extend Sonata 包并定义编译器传递给它。
半年后,我发现了一种更简洁的方法,将服务保留在容器中(因为某处需要它们),但不在管理面板上显示它们。
$definitionsNames = array('sonata.media.admin.media', 'sonata.media.admin.gallery_has_media', 'sonata.media.admin.gallery',
'sonata.classification.admin.category','sonata.classification.admin.tag','sonata.classification.admin.context','sonata.classification.admin.collection');
foreach ($definitionsNames as $definitionName) {
$definition = $container->getDefinition($definitionName);
$tags = $definition->getTags();
$tags['sonata.admin'][0]['show_in_dashboard'] = false;
$definition->setTags($tags);
}
不幸的是,管理路由仍然可用。对我来说这不是问题,但我相信有办法消除它们。
问题是 media_widget 包含一个 link 到管理媒体编辑路由,因此需要覆盖它以不再显示它。然后需要覆盖 Media、Gallery 和 GHM 管理员,并覆盖 configuroutes() 函数并删除所有路由。然后我相信你不能通过管理员访问任何东西,但应用程序仍然可以使用管理服务,如果它们在任何地方需要的话。
这样一来,我还是听从了Radu的建议,不从容器中移除服务。
我将 SonataAdminBundle 与依赖于 ClassificationBundle 的 MediaBundle 一起使用。默认情况下,ClassificationBundle 添加了类别、标签、集合和上下文的后端管理管理,但由于我的应用程序不使用它们,我想从菜单和管理面板中删除它们。
我以前从未删除过服务,所以我不知道该怎么做。
必须有一种方法可以从 SonataClassificationBundle/Resources/config/admin.xml
中删除这些服务,显然不需要修改文件本身,因为它是供应商文件。
<services>
<service id="sonata.classification.admin.category" class="%sonata.classification.admin.category.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_categories" label_catalogue="%sonata.classification.admin.category.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.category.entity%</argument>
<argument>%sonata.classification.admin.category.controller%</argument>
<argument type="service" id="sonata.classification.manager.context" />
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.category.translation_domain%</argument>
</call>
<call method="setTemplates">
<argument type="collection">
<argument key="list">SonataClassificationBundle:CategoryAdmin:list.html.twig</argument>
</argument>
</call>
</service>
<service id="sonata.classification.admin.tag" class="%sonata.classification.admin.tag.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_tags" label_catalogue="%sonata.classification.admin.tag.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.tag.entity%</argument>
<argument>%sonata.classification.admin.tag.controller%</argument>
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.tag.translation_domain%</argument>
</call>
</service>
<service id="sonata.classification.admin.collection" class="%sonata.classification.admin.collection.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_collections" label_catalogue="%sonata.classification.admin.collection.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.collection.entity%</argument>
<argument>%sonata.classification.admin.collection.controller%</argument>
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.collection.translation_domain%</argument>
</call>
</service>
<service id="sonata.classification.admin.context" class="%sonata.classification.admin.context.class%">
<tag name="sonata.admin" manager_type="orm" group="sonata_classification" label="label_contexts" label_catalogue="%sonata.classification.admin.context.translation_domain%" label_translator_strategy="sonata.admin.label.strategy.underscore" />
<argument />
<argument>%sonata.classification.admin.context.entity%</argument>
<argument>%sonata.classification.admin.context.controller%</argument>
<call method="setTranslationDomain">
<argument>%sonata.classification.admin.context.translation_domain%</argument>
</call>
</service>
</services>
或者是否有办法将它们从 Sonata 管理池中删除?因为它们被标记为 sonata.admin
?
编辑
使用 Sonata Easy Extends 我已经扩展了包并添加了一个 Compiler Pass:
class ApplicationSonataClassificationBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'SonataClassificationBundle';
}
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new CustomCompilerPass());
}
}
编译过程看起来像这样
class CustomCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$container->removeDefinition('sonata.classification.admin.category');
}
}
但我得到
You have requested a non-existent service "sonata.classification.admin.cate
gory" in . (which is being imported from "E:\svn\parkresort\app/config\rout
ing/sonata.yml").
该文件正在导入整个奏鸣曲包的路由
admin:
resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml'
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin
#sonata media
media:
resource: '@SonataMediaBundle/Resources/config/routing/media.xml'
prefix: /media
我猜即使从容器中删除后,奏鸣曲管理员仍在使用该服务。我该如何改变它?
EDIT2
我做到了!我必须将 Compiler Pass 放在 Sonata Admin Extension(及其命名空间)中,而不是放在 Sonata Media 中。显然,还扩展了管理包。之后工作得很好。
我不太明白为什么在我的扩展包之后加载原始包时它会起作用:
//AppKernel.php
new ApplicationSonataAdminBundle(),//extended
new Sonata\AdminBundle\SonataAdminBundle(),
真奇怪。
由于我们讨论的是依赖于您的应用程序的捆绑包,因此您无法控制它定义和注册到您的应用程序中的服务。
我相信可以使用 ContainerBuilder::removeDefinition() 删除它们。它也适用于其他包中定义的服务,因此它适用于 Sonata 包。
您可以在 Symfony's documentation 中查看有关将此代码放置在何处以及如何访问 ContainerBuilder
对象的示例。
但是,我建议你不要这样做。即使您不会使用某些服务,它们也不会打扰您,而且考虑到 Symfony 处理服务的方式,它们不会在生产中造成任何性能问题,我保证。
您将需要创建编译器传递以删除定义。 为了能够做到这一点,您必须确保您的捆绑包是在奏鸣曲之后声明的。如果您无法控制它,那么 extend Sonata 包并定义编译器传递给它。
半年后,我发现了一种更简洁的方法,将服务保留在容器中(因为某处需要它们),但不在管理面板上显示它们。
$definitionsNames = array('sonata.media.admin.media', 'sonata.media.admin.gallery_has_media', 'sonata.media.admin.gallery',
'sonata.classification.admin.category','sonata.classification.admin.tag','sonata.classification.admin.context','sonata.classification.admin.collection');
foreach ($definitionsNames as $definitionName) {
$definition = $container->getDefinition($definitionName);
$tags = $definition->getTags();
$tags['sonata.admin'][0]['show_in_dashboard'] = false;
$definition->setTags($tags);
}
不幸的是,管理路由仍然可用。对我来说这不是问题,但我相信有办法消除它们。 问题是 media_widget 包含一个 link 到管理媒体编辑路由,因此需要覆盖它以不再显示它。然后需要覆盖 Media、Gallery 和 GHM 管理员,并覆盖 configuroutes() 函数并删除所有路由。然后我相信你不能通过管理员访问任何东西,但应用程序仍然可以使用管理服务,如果它们在任何地方需要的话。
这样一来,我还是听从了Radu的建议,不从容器中移除服务。