Description
Q | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Symfony version | >=2.8.0 (incl. 3.2.6) |
In some cases a success of building DIC container depends on order of definitions in services.yml
.
I think that a tangible example is the best way to explain this issue.
services.yml
:
services:
str_trans2:
class: AppBundle\Model\String\StringTransformer2
autowire: true
str_trans:
class: AppBundle\Model\String\StringTransformer
autowire: true
StringTransformer.php
:
class StringTransformer {
public function __construct(MyRepository $myRepository) {};
}
StringTransformer2.php
:
class StringTransformer2 {
public function __construct(RepositoryInterface $repository) {};
}
MyRepository.php
:
class MyRepository implements RepositoryInterface {}
RepositoryInterface.php
:
interface RepositoryInterface {}
When you have the configuration above in your application Symfony fails to build the container with an error:
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
Unable to autowire argument of type "RepositoryInterface" for the service "str_trans2". No services were found matching this interface and it cannot be auto-registered.
That is because MyRepository
is not registered explicitly in services.yml
. While AutowirePass
can auto-register classes it first processes the str_trans2
definition and fails because MyRepository
was not auto-registered yet and would be registered into container only after processing str_trans
definition.
If you swap the order of definitions in services.yml
(put str_trans
before str_trans2
) the situation changes and container can be successfully build. That is because str_trans
is processed first and during this an instance of MyRepository
is registered in the container. So when AutowirePass
processes str_trans2
later it already knows about a service that implements RepositoryInterface
(auto-registered private service autowired.MyRepository
).
This issue was already discussed in PR #22148 and @nicolas-grekas confirmed that it is a bug.
The example above can be downloaded here: https://github.com/sustmi/symfony-standard/tree/autowiring-order-dependent