Override symfony service tag with compiler pass

I am trying to override a tag in a symfony service definition with a compiler pass. An example service will be data_collector.translation

.

The goal is to disable the collection service to disable the item in the symfony web developer toolbar. For this, I need to set the tag priority

tag data_collector

to 0

.

I could also override it in my own definition:

services:

    data_collector.translation:
        class: 'Symfony\Component\Translation\DataCollector\TranslationDataCollector'
        tags:
           - {name: 'data_collector', priority: '0'}
        arguments: [@translator.data_collector]

      

But since I want to do this for multiple data collectors, I will need to know the required arguments to define the data collector. The priority works the same for all collectors, so I would only need the collector name to disable it.

So, I wrote the following compiler run:

class DataCollectorCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('data_collector.translation')) {
            return;
        }
        $definition = $container->getDefinition('data_collector.translation');

        $tags = $definition->getTags();

        $tags['data_collector'][0]['priority'] = 0;

        $definition->setTags($tags);

        $container->setDefinition('data_collector.translation', $definition);
    }
}

      

To make things more wired: when I ran this command:

$ php app/console container:debug --show-private --tag='data_collector'

      

I am getting the following output:

data_collector.translation @WebProfiler/Collector/translation.html.twig translation 0 Symfony\Component\Translation\DataCollector\TranslationDataCollector

      

Thus, the priority is set to even in the debugger 0

.

But for whatever reason the item is still showing in the toolbar.

What did I do wrong here? Is there any other mechanism to overwrite the tag in the compiler pass?

The compiler protocol starts up (tested with printout)
I am using Symfony 2.7.1

+3


source to share


3 answers


It turns out the code works, the only problem is that the CompilerPass runs after the ProfilerPass which is part of the FrameworkBundle

. Putting my package with CompilerPass before FrameworkBundle

in AppKernel

solves the problem (more info here ). In order not to even run the data collectors, it is best to remove all tags rather than just prioritize on 0

.

This is what the final solution looks like:



class DataCollectorCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $collectorsToRemove = [
            'data_collector.form',
            'data_collector.translation',
            'data_collector.logger',
            'data_collector.ajax',
            'data_collector.twig'
        ];

        foreach($collectorsToRemove as $dataCollector) {

            if (!$container->hasDefinition($dataCollector)) {
                continue;
            }
            $definition = $container->getDefinition($dataCollector);

            $definition->clearTags();
        }
    }
}

      

+2


source


Can you try this?



    if (!$container->hasDefinition('data_collector.form')) {
        return;
    }
    $definition = $container->getDefinition('data_collector.form');

    $definition->clearTags();

    $container->setDefinition('data_collector.form', $definition);

      

+1


source


Why don't you use your compiler to directly manipulate the Definition

service that contains all these collectors?

If I look at the compiler responsible for loading the data collector , it seems that they were all injected with method call injection.

You can use your compiler to overwrite the array method calls by using techniques such as setMethodCalls

, removeMethodCall

... the object Definition

.

Method call handling documentation: link

+1


source







All Articles