Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why logger service can't be injected in the CompilerPass?

Tags:

symfony

I execute this command

app/console container:debug | grep logger

clearly, there is a service named logger:

 logger                                                             Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.assetic                                             Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.doctrine                                            Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.event                                               Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.php                                                 Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.profiler                                            Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.request                                             Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.router                                              Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.security                                            Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.templating                                          Symfony\Bridge\Monolog\Logger                                                              
 monolog.logger.translation                                         Symfony\Bridge\Monolog\Logger                                                              
 swiftmailer.mailer.default.plugin.messagelogger                    Swift_Plugins_MessageLogger                                                                
 swiftmailer.plugin.messagelogger                                   alias for "swiftmailer.mailer.default.plugin.messagelogger"     

I inject the service using this code:

public function process(ContainerBuilder $container)
{
    $clients= $container->findTaggedServiceIds('socket.client');

    foreach ($clients as $id => $tags) {
        $definition = $container->getDefinition($id);
        $definition->addArgument($container->getDefinition('logger'));
    }
}

But I got this error:

Symfony\Component\DependencyInjection\Exception\InvalidArgumentException] The service definition "logger" does not exist.

If change the logger service to monolog.logger.doctrine, then everything is fine, what happened with logger service?

Another interesting thing is that even though the above way didn't work , it works in in yml, I can inject the logger service

services:
    etc.socket.server:
        class: %etc.socket.server.class%
        arguments: [@logger, @event_dispatcher, @etc.encoder,@etc.message.client.request]

the reason I have to inject the logger service in code , because I have several socket.client services, and they are defined in the code.

Update:

I can find the logger service definition in appDevDebugProjectContainer.xml :

 <service id="logger" class="Symfony\Bridge\Monolog\Logger">
      <argument>app</argument>
      <call method="pushHandler">
        <argument type="service" id="monolog.handler.console"/>
      </call>
      <call method="pushHandler">
        <argument type="service" id="monolog.handler.main"/>
      </call>
      <call method="pushHandler">
        <argument type="service" id="monolog.handler.debug"/>
      </call>
 </service>

even though I write a compile pass to inject the logger service , it still doesn't work

public function process(ContainerBuilder $container)
    {

        $clients = $container->findTaggedServiceIds('micro_pay.socket.client');

        foreach ($clients as $id => $tags) {
            $definition = $container->getDefinition($id);

             $loggerDefinition=$container->findDefinition('logger');  //$loggerDefinition  is null
//            $definition->addArgument($loggerDefinition);  
        }
    }

why the logger service is such special?

like image 636
Vidy Videni Avatar asked Dec 07 '15 03:12

Vidy Videni


2 Answers

Have you tried using the reference instead?

$definition->addArgument(new Reference('logger'));

The definition might not exist yet at this point. You never set the actual definition in your argument, you set a reference to a service.

like image 183
Anyone Avatar answered Oct 28 '22 09:10

Anyone


Try using the method findDefinition instead of getDefinition on ContainerBuilder class as described in the doc.

As Example:

Use this:

    $definition->addArgument($container->findDefinition('logger'));

instead of this:

    $definition->addArgument($container->getDefinition('logger'));

The main difference between the two methods is about the resolutions of aliases service

findDefinition: The method "unaliases" recursively to return a Definition instance

Further reference in the source code here.

Hope this help

like image 27
Matteo Avatar answered Oct 28 '22 09:10

Matteo