phpstan-symfony
phpstan-symfony copied to clipboard
Support `#[AutowireLocator]`
Symfony 6.4 introduced an attribute called #[AutowireLocator] which automatically creates and injects a ServiceLocator into a service. Looks like a similar feature was already implemented with #151.
Is it possible to add support for this feature, too?
final class TranscriptAdmin
{
// ...
#[Required]
public function setContainer(
#[AutowireLocator([ProfileRepository::class])] ContainerInterface $container
): void {
$this->locator = $container;
}
}
------ ----------------------------------------------------------------------
Line src/TranscriptBundle/Admin/TranscriptAdmin.php
------ ----------------------------------------------------------------------
56 Service "App\ProfileBundle\Repository\ProfileRepository" is private.
✏️ src/TranscriptBundle/Admin/TranscriptAdmin.php
------ ----------------------------------------------------------------------
The current workaround is to use // @phpstan-ignore symfonyContainer.privateService above the line where we use $this->locator->get. Of course this is not a nice solution.
Looking at https://github.com/phpstan/phpstan-symfony/blob/1ef4dce2baabd464c2dd3109d051bad94efa1e79/src/Rules/Symfony/ContainerInterfacePrivateServiceRule.php and #151 it shouldn't be very hard to implement a fix, unfortunately I currently don't have time for that.
I just implemented support for the basic syntax as described in the OP (#[AutowireLocator([ProfileRepository::class])]). See https://github.com/phpstan/phpstan-symfony/pull/420
I actually took the time and implemented AutowireLocator attribute support in #420 Currently there are some failing checks I can't resolve, but besides from that everything should be ready!
I have the same problem, but instead of defining specific services, I use a tag instead, so the container contains all services with this tag. This is also allowed by Symfony and the services don't have to be public to access them this way through this limited container. Could you consider this kind of usage too when fixing the issue? Thanks a lot!
#[AutoconfigureTag('app.some_tag')]
interface SomeInterface { }
class SomeServiceA implements SomeInterface { }
class SomeServiceB implements SomeInterface { public function doSomething(): void { } }
class SomeServiceC implements SomeInterface { }
class MainService {
public function __construct(
#[AutowireLocator('app.some_tag')]
private ContainerInterface $myServices,
) { }
public function someMethod(): void {
$this->myServices->get(SomeServiceB::class)->doSomething();
}
}