Skip to content

Cannot autowire service (...) when using #[Target] attribute in Symfony 6.3 #50541

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Kocal opened this issue Jun 2, 2023 · 4 comments
Closed

Comments

@Kocal
Copy link
Member

Kocal commented Jun 2, 2023

Symfony version(s) affected

6.3.0

Description

Hi,

While upgrading our application from Symfony 6.2.x to 6.3, I faced an issue about when using the #[Target] attribute in a Command's constructor.

With the following code:

#[AsCommand(
    name: 'app:website:generate:sitemap',
    description: 'Generate sitemaps for all websites.',
)]
class GenerateSitemapsCommand extends Command
{
    public function __construct(
        #[Target('console')] private LoggerInterface $logger,
        private SitemapGenerator $sitemapGenerator,
        private WebsiteRepository $websiteRepository,
        private Clock $clock,
        private WebsiteSwitcher $websiteSwitcher
    ) {
        parent::__construct();
    }

    // ... 
}

I have the following error with Symfony 6.3 (it works fine with Symdony 6.2):

symfony console c:cl -v

In DefinitionErrorExceptionPass.php line 51:

  [Symfony\Component\DependencyInjection\Exception\RuntimeException]
  Cannot autowire service "App\Command\Website\GenerateSitemapsCommand": "#[Target('console')" on argument "$logger" of method "__construct()"


Exception trace:
  at /Users/halliaume/workspace/international-website/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php:51
 Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass->processValue() at /Users/halliaume/workspace/international-website/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php:86
 Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->processValue() at /Users/halliaume/workspace/international-website/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php:29
 Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass->processValue() at /Users/halliaume/workspace/international-website/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php:47
 Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->process() at /Users/halliaume/workspace/international-website/vendor/symfony/dependency-injection/Compiler/Compiler.php:80
 Symfony\Component\DependencyInjection\Compiler\Compiler->compile() at /Users/halliaume/workspace/international-website/vendor/symfony/dependency-injection/ContainerBuilder.php:767
 Symfony\Component\DependencyInjection\ContainerBuilder->compile() at /Users/halliaume/workspace/international-website/vendor/symfony/http-kernel/Kernel.php:506
 Symfony\Component\HttpKernel\Kernel->initializeContainer() at /Users/halliaume/workspace/international-website/vendor/symfony/http-kernel/Kernel.php:757
 Symfony\Component\HttpKernel\Kernel->preBoot() at /Users/halliaume/workspace/international-website/vendor/symfony/http-kernel/Kernel.php:126
 Symfony\Component\HttpKernel\Kernel->boot() at /Users/halliaume/workspace/international-website/vendor/symfony/framework-bundle/Console/Application.php:154
 Symfony\Bundle\FrameworkBundle\Console\Application->registerCommands() at /Users/halliaume/workspace/international-website/vendor/symfony/framework-bundle/Console/Application.php:72
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /Users/halliaume/workspace/international-website/vendor/symfony/console/Application.php:174
 Symfony\Component\Console\Application->run() at /Users/halliaume/workspace/international-website/vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:54
 Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner->run() at /Users/halliaume/workspace/international-website/vendor/autoload_runtime.php:29
 require_once() at /Users/halliaume/workspace/international-website/bin/console:21

Note that the Monolog handler console is properly defined.

Thanks!

How to reproduce

See https://github.com/Kocal/sf6.3-reproducer-autowiring-target-attribute for reproduction repository and steps.

Possible Solution

No response

Additional Context

No response

@stof
Copy link
Member

stof commented Jun 2, 2023

Target takes a service id. And I doubt that you have a logger registered under the id console (All services registered by MonologBundle have a monolog. prefix, except the logger alias that is redefined to use the monolog logger)

@HypeMC
Copy link
Contributor

HypeMC commented Jun 2, 2023

Try running bin/console debug:container, I'm pretty sure it should be

#[Target('consoleLogger')] private LoggerInterface $logger

It looks like an invalid target name was ignored in previous versions Symfony and the default logger was used.

@HypeMC
Copy link
Contributor

HypeMC commented Jun 2, 2023

Target takes a service id. And I doubt that you have a logger registered under the id console (All services registered by MonologBundle have a monolog. prefix, except the logger alias that is redefined to use the monolog logger)

Actually no, it takes the alias of the parameter name, not the service id:

$ bin/console debug:container
...
  Psr\Log\LoggerInterface $consoleLogger                alias for "monolog.logger.console"

@Kocal
Copy link
Member Author

Kocal commented Jun 2, 2023

Hum, well... It looks like our #[Target('console')] (and others without logger suffix) never worked as expected, they failed silently.

If I debug the service monolog.logger.console, I can see it is not used in our GenerateSitemapsCommand class:

symfony console debug:container monolog.logger.console

Information for Service "monolog.logger.console"
================================================

 ---------------- -------------------------------------------
  Option           Value
 ---------------- -------------------------------------------
  Service ID       monolog.logger.console
  Class            Symfony\Bridge\Monolog\Logger
  Tags             -
  Calls            pushProcessor, pushProcessor, pushHandler
  Public           no
  Synthetic        no
  Lazy             no
  Shared           yes
  Abstract         no
  Autowired        no
  Autoconfigured   no
  Usages           Psr\Log\LoggerInterface $consoleLogger
                   console.error_listener
 ---------------- -------------------------------------------


 ! [NOTE] The "monolog.logger.console" service or alias has been removed or inlined when the container was compiled.

But if I switch to #[Target('consoleLogger')], then it is used in our GenerateSitemapsCommand:

symfony console debug:container monolog.logger.console

Information for Service "monolog.logger.console"
================================================

 ---------------- ---------------------------------------------
  Option           Value
 ---------------- ---------------------------------------------
  Service ID       monolog.logger.console
  Class            Symfony\Bridge\Monolog\Logger
  Tags             -
  Calls            pushProcessor, pushProcessor, pushHandler
  Public           no
  Synthetic        no
  Lazy             no
  Shared           yes
  Abstract         no
  Autowired        no
  Autoconfigured   no
  Usages           Psr\Log\LoggerInterface $consoleLogger
                   App\Command\Website\GenerateSitemapsCommand
                   console.error_listener
 ---------------- ---------------------------------------------


 ! [NOTE] The "monolog.logger.console" service or alias has been removed or inlined when the container was compiled.

Thanks!

@Kocal Kocal closed this as completed Jun 2, 2023
javiereguiluz added a commit to symfony/symfony-docs that referenced this issue Jun 24, 2024
…(HypeMC)

This PR was merged into the 5.4 branch.

Discussion
----------

[DependencyInjection] Clarify the `#[Target]` attribute

The `#[Target]` attribute seems to be a constant source of confusion for developers, as evident by:

- symfony/symfony#50541
- symfony/symfony#51565
- symfony/symfony#54578

Also, the example given is either unclear or just wrong. Hopefully, this helps clarify things.

Commits
-------

2fb1ada [DependencyInjection] Clarify the `#[Target]` attribute
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants