phpstan-symfony
phpstan-symfony copied to clipboard
AutowireLocator does not work well
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:
https://github.com/lyrixx/test/commit/e172840d514a00c3ed8667e828a4197a3028c782#r154945352
(ref https://github.com/symfony/symfony/pull/60096#issuecomment-2782785035)
I don't get it. Please explain the problem.
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
This belongs to phpstan-symfony.
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
Same problem with Symfony\Contracts\Service\ServiceSubscriberInterface
There are several issues / PR related to the container : #352 #89 #420 #252 #411 #338 #321 #79 #74 #28