Как удалить службу Symfony? (Сонатная классификация)

Я использую SonataAdminBundle с MediaBundle, который зависит от ClassificationBundle. По умолчанию 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

Я предполагаю, что служба используется администратором сонаты даже после удаления из контейнера. Как я могу это изменить?

ИЗМЕНИТЬ2

Я сделал это! Мне пришлось поместить Compiler Pass в расширение Sonata Admin (с его пространством имен), а не в Sonata Media. Также, очевидно, расширение пакета администратора. После работал нормально.

Чего я действительно не понимаю, так это почему это работает, когда исходный пакет загружается после моего расширенного пакета:

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

Это странно.


person George Irimiciuc    schedule 18.12.2015    source источник


Ответы (3)


Поскольку мы говорим о пакете, который является зависимостью вашего приложения, вы не можете контролировать, какие сервисы он определяет и регистрирует в вашем приложении.

Я считаю, что их можно удалить с помощью ContainerBuilder. ::удалитьопределение(). Он будет работать и для сервисов, определенных в других пакетах, поэтому он будет работать и с пакетом Sonata.

Вы можете увидеть пример в документации Symfony, где именно разместить этот код. и как получить доступ к объекту ContainerBuilder.

Однако я советую вам этого не делать. Даже если вы не будете использовать некоторые сервисы, они не будут вас беспокоить, и, учитывая то, как Symfony обрабатывает сервисы, я обещаю, что они не вызовут проблем с производительностью в продакшене.

person Radu Murzea    schedule 18.12.2015
comment
Они не беспокоят меня, но они беспокоят моего клиента. Он может «играть» там и что-то сломать, или они могут просто захотеть удалить эти ненужные категории. Это проблема. Кроме того, почему бы вам не посоветовать это? Какие проблемы могут быть? Услуги администратора больше нигде не используются. - person George Irimiciuc; 19.12.2015
comment
@GeorgeIrimiciuc Это как иметь машину. А ты полностью убери заднее сиденье. Вы скажете себе, что это не проблема, у вас все равно не будет пассажиров. И это не будет проблемой.... пока это не будет. Потому что в какой-то момент кто-то будет ожидать, что эти службы будут там, и попытается их использовать... и когда они потерпят неудачу, они потеряют дни, пытаясь понять, что происходит. - person Radu Murzea; 19.12.2015
comment
Можно снять заднее сиденье, если в машине не должно быть пассажиров. Если это то, о чем просит покупатель. И в данном конкретном случае эти услуги точно никто не пропустит. - person George Irimiciuc; 19.12.2015

Вам нужно будет создать проход компилятора, чтобы удалить определение. Чтобы иметь возможность сделать это, вы должны убедиться, что ваш пакет объявлен после пакета Sonata. Если вы не можете это контролировать, тогда расширьте комплект Sonata и определите компилятор проходит в него.

person gvf    schedule 18.12.2015
comment
Это странно. Если я добавлю его позже, я получу ошибку в первом редактировании моего вопроса: «Вы запросили несуществующую услугу». Но если я сначала позволю, а затем добавлю оригинальную Sonata в AppKernel.php, все будет работать нормально. - person George Irimiciuc; 05.01.2016

Спустя пол года я нашел гораздо более чистый способ, который держит сервисы в контейнере (потому что они где-то нужны), но не показывает их в админке.

   $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 содержит ссылку на маршрут редактирования мультимедиа администратора, поэтому его необходимо перезаписать, чтобы он больше не отображался. Затем необходимо переопределить администраторов Media, Gallery и GHM, переопределить функцию configureroutes() и удалить все маршруты. Тогда я считаю, что вы не можете получить доступ к чему-либо через администратора, но приложение все равно может использовать службы администратора, если они где-либо нужны.

Таким образом, я все еще следую совету Раду не удалять сервисы из контейнера.

person George Irimiciuc    schedule 08.06.2016