Skip to content

[DI] Successful construction of DIC depends on order of service definitions when depending on an interface which implementation is auto-registered #22162

Closed
@sustmi

Description

@sustmi
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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions