Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[DI] [DX] Suggest what to do when container fails to autowire an inteface#22148

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

@sustmi
Copy link
Contributor

@sustmisustmi commentedMar 24, 2017
edited
Loading

QA
Branch?master
Bug fix?no
New feature?no
BC breaks?no
Deprecations?no
Tests pass?yes
Fixed ticketsnone
LicenseMIT
Doc PRnone

Lets consider this example files:

class Service1 {publicfunction__construct(MyInterface$my) {}}
class Service2implements MyInterface {}

If you have the serviceService2 defined beforeService1 in yourservices.yml file then everything is OK.
But if you haveService1 first andService2 second you will get the following exception:

[Symfony\Component\DependencyInjection\Exception\RuntimeException]Cannot autowire argument $my of method AppBundle\Model\Service1::__construct() for service "my_service1": No services were found matching the "AppBundle\Model\MyInterface" interface and it cannot be auto-registered.

Another example: The same happens if you do not haveService2 in yourservices.yml and you want to autowire this:

class Service3 {// Note that the interface is to be autowired before the service implementing the interfacepublicfunction__construct(MyInterface$my1,Service2$my2)}

After this PR the exception message changes to:

[Symfony\Component\DependencyInjection\Exception\RuntimeException]Cannot autowire argument $my1 of method AppBundle\Model\Service3::__construct() for service "my_service3": No services were found matching the "AppBundle\Model\MyInterface" interface and it cannot be auto-registered. Make sure that a service implementing "AppBundle\Model\MyInterface" interface is registered in the container before registering service "my_service3".

Notice the last sentence. It suggests the developer what is the common case for this mistake and what can be the solution.

UPDATE: The first described example actually does not cause any problem. Seehttps://github.com/sustmi/symfony-standard/tree/autowiring-order-dependent for another example that presents the problem.

@carsonbotcarsonbot added Status: Needs Review DependencyInjection DXDX = Developer eXperience (anything that improves the experience of using Symfony) labelsMar 24, 2017
@sustmisustmiforce-pushed theclarify-service-not-found-message-in-autowire-pass branch from530541b to7052cc3CompareMarch 24, 2017 13:34
@sustmi
Copy link
ContributorAuthor

sustmi commentedMar 24, 2017
edited
Loading

(Sorry for the push-force. There were some typos. Now it should be OK.)

@theofidry
Copy link
Contributor

Isn't the autowiring pass ran much later to avoid those issues?

@stof
Copy link
Member

the order of service definition should not matter, as this code runs in a compiler pass, so after the whole file is loaded

@sustmi
Copy link
ContributorAuthor

sustmi commentedMar 24, 2017
edited
Loading

In Symfony 3.2.6 the order of service definition matters. I tested it. You can try it on the examples I posted in PR.

@theofidry
Copy link
Contributor

@sustmi I'm using 3.2.6 and I don't have this issue. Could you try to reproduce it in a fork of the Standard Edition?

@nicolas-grekas
Copy link
Member

Can you please try#22135?
Does it fix your issue?

@nicolas-grekasnicolas-grekas added this to the3.3 milestoneMar 24, 2017
@sustmi
Copy link
ContributorAuthor

sustmi commentedMar 24, 2017
edited
Loading

@theofidry: I am sorry, the example in the PR is probably a bad one.
However here is a branch with an evidence that autowiring does depend on order of definitions:https://github.com/sustmi/symfony-standard/tree/autowiring-order-dependent

Try running php bin/console server:run. It will fail to compile the container.
Then swap services in services.yml and try it again (str_trans before str_trans2). It will work.

@sustmi
Copy link
ContributorAuthor

sustmi commentedMar 24, 2017
edited
Loading

@nicolas-grekas: When I run the new example (https://github.com/sustmi/symfony-standard/tree/autowiring-order-dependent) on Symfony 3.2.6 the error message is:

Unable to autowire argument of type "AppBundle\Model\RepositoryInterface" for the service "str_trans2". No services were found matching this interface and it cannot be auto-registered.

while when I update Symfony to your PR (d7557cf) the message is following:

Cannot autowire service "str_trans2": no services were found matching the "AppBundle\Model\RepositoryInterface" interface and it cannot be auto-registered for argument $myRepository of method AppBundle\Model\String\StringTransformer2::__construct().

Both does not tell anything that would make developer think about the order of definitions.
But I guess by the other comments that the dependency on order is more a bug than an undocumented feature.
Can anyone confirm that?

…rfaceLets consider this example (two php files):---class Service1 {    public function __construct(MyInterface $my) ...}class Service2 implements MyInterface {}---If you have the service Service2 defined before Service1 in your services.yml file then everything is OK.But if you have Service1 first and Service2 second you will get the following exception:---[Symfony\Component\DependencyInjection\Exception\RuntimeException]Cannot autowire argument $my of method AppBundle\Model\Service1::__construct() for service "my_service1": No services were found matching the "AppBundle\Model\MyInterface" interface and it cannot be auto-registered.---The same happens if you do not have Service2 in your services.yml and you want to autowire this:---class Service3 {    // Note that the interface is to be autowired before the service implementing the interface    public function __construct(MyInterface $my1, Service2 $my2)}---After this commit the exception message changes to:---[Symfony\Component\DependencyInjection\Exception\RuntimeException]Cannot autowire argument $my1 of method AppBundle\Model\Service3::__construct() for service "my_service3": No services were found matching the "AppBundle\Model\MyInterface" interface and it cannot be auto-registered. Make sure that a service implementing "AppBundle\Model\MyInterface" interface is registered in the container before registering service "my_service3".---Notice the last sentence. It suggests the developer what is the common case for this mistake and what can be the solution.
@sustmisustmiforce-pushed theclarify-service-not-found-message-in-autowire-pass branch from7052cc3 to749d14eCompareMarch 24, 2017 23:40
@sustmi
Copy link
ContributorAuthor

Meanwhile I updated the PR for the current master.

@sustmi
Copy link
ContributorAuthor

sustmi commentedMar 25, 2017
edited
Loading

To clarify the issue the problem with wrong order happens when DIC has to auto-register a class and not when all services are registered explicitly inservices.yml.

The working example (StringTransformer beforeStringTransformer2) has following flow:

  1. AutowirePass processesStringTransformer
  2. It finds that it has one dependency -MyRepository
  3. It looks into definitions found inservices.yml and does not see this class
  4. It auto-registersMyRepository and then resolves the dependency forStringTransformer
  5. ThenAutowirePass processesStringTransformer2
  6. It finds that it has one dependency -RepositoryInterface
  7. It sees that there is an implementation of this interface already registered so it resolves the dependency

Thenot working example (StringTransformer2 beforeStringTransformer) has following flow:

  1. AutowirePass processesStringTransformer2
  2. It finds that it has one dependency -RepositoryInterface
  3. It looks into definitions found inservices.yml and sees nothing that implementsRepositoryInterface so it fails (MyRepository was not auto-registered yet because no service depending on this class was processed yet).

@nicolas-grekas
Copy link
Member

I confirm it's a bug. Not a trivial one to fix I'd say. Can you open an issue please, then I think we can close this PR.

@sustmi
Copy link
ContributorAuthor

@nicolas-grekas: I opened a new issue#22162 as you advised and now I am closing this PR.

@sustmisustmi closed thisMar 25, 2017
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

DependencyInjectionDXDX = Developer eXperience (anything that improves the experience of using Symfony)Status: Needs Review

Projects

None yet

Milestone

3.3

Development

Successfully merging this pull request may close these issues.

5 participants

@sustmi@theofidry@stof@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp