简体   繁体   中英

How to remove a Symfony service? (Sonata Classification)

I'm using SonataAdminBundle with MediaBundle that has a dependency on ClassificationBundle. By default, ClassificationBundle adds in backend admin management for categories, tags, collections and contexts, but since my application doesn't use them I want to remove them from the menu and admin panel.

I've never removed a service before, so I don't know how to do it.

There has to be a way to remove these services from SonataClassificationBundle/Resources/config/admin.xml , obviously without modifying the file itself because it is a vendor file.

 <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>

Or maybe is there a way to remove them from the Sonata admin pool? Since they are tagged with sonata.admin ?

EDIT

Using Sonata Easy Extends I've extended the bundle and added a Compiler Pass:

class ApplicationSonataClassificationBundle extends Bundle
{
    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return 'SonataClassificationBundle';
    }

    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $container->addCompilerPass(new CustomCompilerPass());
    }

}

The compiler pass looks like this

class CustomCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $container->removeDefinition('sonata.classification.admin.category');
    }
}

But I'm getting

  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").

That file is importing the routing for the whole sonata bundle

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

I guess the service is being used by sonata admin even after being removed from the container. How can I change that?

EDIT2

I did it! I had to put the Compiler Pass in Sonata Admin Extension(with its namespace) and not in Sonata Media. Also extending the Admin bundle, obviously. Worked just fine afterwards.

What I don't really understand is why it works when the original bundle is loaded after my extended bundle:

//AppKernel.php
new ApplicationSonataAdminBundle(),//extended
new Sonata\AdminBundle\SonataAdminBundle(),

That is strange.

Since we're talking about a bundle which is a dependency of your application, you have no control over what services it defines and registers into your application.

I believe it's possible to remove them using ContainerBuilder::removeDefinition() . It will work for services defined in other bundles as well, therefore it will work on the Sonata bundle.

You can see an example in Symfony's documentation on exactly where to put this code and how to gain access to the ContainerBuilder object.

However, I advise you to not do this. Even though you won't use some services, they won't bother you and, given how Symfony handles services, they won't cause any performance problems in production, I promise.

You will need to create a compiler pass to remove the definition. In order to be able to do that you have to make sure your bundle is declared after the Sonata one. If you can't control that, then extend the Sonata bundle and define the compiler pass in it.

Half a year later, I found a much cleaner way that keeps the services in the container(because they are needed somewhere), but doesn't show them on the admin panel.

   $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);

    }

Unfortunately, the admin routes are still available. Not an issue for my side, but I believe there are ways to remove them. The thing is the media_widget contains a link to the admin media edit route, so that needs to be overwritten to not show it anymore. Then the Media, Gallery and GHM admins need to be overridden, and override the configureroutes() function and remove all routes. Then I believe you can't access anything through the admin, but the application can still use the admin services, if they are needed anywhere.

This way, I still follow Radu's advice of not removing services from the container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM