Skip to content

AutowireLocator does not work well #440

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

Open
lyrixx opened this issue Apr 7, 2025 · 4 comments
Open

AutowireLocator does not work well #440

lyrixx opened this issue Apr 7, 2025 · 4 comments

Comments

@lyrixx
Copy link

lyrixx commented Apr 7, 2025

When we inject a ServiceLocator, the extension does not understand that.
It thinks it's the full container, but it's not. It's a specialed container.

I made a full reproducer:

lyrixx/test@e172840#r154945352

(ref symfony/symfony#60096 (comment))

@ondrejmirtes
Copy link
Member

I don't get it. Please explain the problem.

@lyrixx
Copy link
Author

lyrixx commented Apr 7, 2025

edit I just noticed this issue should be move to phpstan/phpstan-symfony

In Symfony, you can type hint a parameter with ContainerInterface, but when you add the #[AutowireLocator] attribute, it won't inject the service_container (the real / huge container). Instead it will inject a smaller, specialized container with only few services.

Example:

 class Foo
 {
     public function __construct(
         #[AutowireLocator(MyInterface::class)]
         private ContainerInterface $container,
     ) {}
 
     public function consume(): void
     {
         $this->container->get(Foo::class);
     }
 }

Here, in $this->container, there is only services where the definition is tagged with "App\Reproducer\MyInterface" (here, only Foo service).

If you look at the the dumped definition:

    <service id="App\Reproducer\Consumer" class="App\Reproducer\Consumer" autowire="true" autoconfigure="true">
      <argument type="service" id=".service_locator.ExRZJjZ"/>
    </service>
    <service id=".service_locator.ExRZJjZ" class="Symfony\Component\DependencyInjection\ServiceLocator">
      <tag name="container.service_locator"/>
      <argument type="collection">
        <argument key="App\Reproducer\Foo" type="service_closure" id="App\Reproducer\Foo"/>
      </argument>
    </service>

You can also specified some service ids:

    public function __construct(
        #[AutowireLocator([
            FooHandler::class,
            BarHandler::class,
        ])]
        private ContainerInterface $handlers,
    ) {
    }

If I'm not clear enough, you can read the symfony doc


When running phpstan on this code, it thinks the container is the whole symfony container.
And so it tells us the service App\Reproducer\Foo is private. It is in the whole container, but it is not in the real injected container.

So, when a container is injected, phpstan should check if it's the whole service_container or a smaller container

@ondrejmirtes
Copy link
Member

This belongs to phpstan-symfony.

@lyrixx
Copy link
Author

lyrixx commented Apr 7, 2025

This belongs to phpstan-symfony.

Yes, that what I said in my latest comment. I have no right to move this issue. Could you do it for me? Thanks

@ondrejmirtes ondrejmirtes transferred this issue from phpstan/extension-installer Apr 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants