Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Autowiring confuses argument order in some cases #17724

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
weaverryan opened this issue Feb 8, 2016 · 10 comments
Closed

Autowiring confuses argument order in some cases #17724

weaverryan opened this issue Feb 8, 2016 · 10 comments

Comments

@weaverryan
Copy link
Member

Hi guys!

Take the following class:

class ProductRepository
{
    private $client;
    private $logger;

    public function __construct(Client $client, LoggerInterface $logger)
    {
        $this->client = $client;
        $this->logger = $logger;
    }
}

Since LoggerInterface can't be injected yet (we're waiting on a MonologBundle tag), I wired it like this:

services:
    product_repository:
        class: AppBundle\Repository\ProductRepository
        autowire: true
        arguments:
            1: '@logger'

Sure, it's weird to have the "1" in there, but I thought it would work. It almost did, but it reversed the arguments. In the cached container, this becomes:

new ProductRepository($this->get('logger'), $this->get('api_client'));

In YAML, I believe this is the only way to set one specific argument, without specifying all of them, and it looks like a bug :).

Especially because non-services can't be autowired yet, this probably the biggest issue left with autowiring (along with not being able to globally map a class/interface to a specific service id).

ping @dunglas

Thanks!

@linaori
Copy link
Contributor

linaori commented Feb 9, 2016

Might be a weird brainfart, but what about allowing a map of <number>: <argument> under autowire additionally to true? This would leave the arguments as is without modifications but allows any edge-cases configurable under the autowire key.

@weaverryan
Copy link
Member Author

@iltar So first, there is still a bug here - I want to make sure we keep that focus :).

But, your idea is interesting. Well actually, if it weren't for this bug, you can already do what you're saying, just under the arguments keys using indexes 0, 1, 2, etc. However, it might be interesting with autowiring to allow named arguments - as it's a bit weird to specify your "argument index 1" value. So then:

services:
    product_repository:
        class: AppBundle\Repository\ProductRepository
        autowire:
            logger: '@logger'

In theory, this could also still just be done under arguments (it's just a different way of specifying arguments), but autowiring is the only thing currently that uses reflection (needed to get the arg name)... so I'm not sure if it would make sense there. But maybe :)

@dunglas
Copy link
Member

dunglas commented Feb 11, 2016

@weaverryan this use case is already supported (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php#L75)

The following snippet should work:

services:
    product_repository:
        class: AppBundle\Repository\ProductRepository
        autowire: true
        arguments: [ '', '@logger' ]

@dunglas
Copy link
Member

dunglas commented Feb 11, 2016

It looks weird in YAML (but works), it's far better in XML:

<service id="product_repository" class="AppBundle\Repository\ProductRepository" autowire="true">
    <argument />
    <argument type="service" id="logger" />
</service>

@weaverryan
Copy link
Member Author

@dunglas

You're right - but it's odd: if I use your same syntax but with null, it'll fail:

services:
    product_repository:
        class: AppBundle\Repository\ProductRepository
        autowire: true
        arguments:
            - ~
            - '@logger'

Anyways, with your working example, it just doesn't feel right. One day, autowiring might work great. Then suddenly I add a 4th constructor argument that can't be autowired. Suddenly I need to add 5 lines (arguments and the lines below) to make the service work again:

services:
    product_repository:
        class: AppBundle\Repository\ProductRepository
        autowire: true
        arguments:
            - ''
            - ''
            - ''
            - ''
            - '%kernel.root_dir%'

And if we change the order of the args (something autowiring should allow), it'll break.

What do you think about my previous suggestion? #17724 (comment)

@dunglas
Copy link
Member

dunglas commented Feb 15, 2016

@weaverryan it makes a lot of sense to enhance this feature. I personally prefer you're proposal of using:

services:
    product_repository:
        class: AppBundle\Repository\ProductRepository
        autowire: true
        arguments:
            1: '@logger'

Because it couples less the code with the configuration. With named parameters, if you rename a constructor parameter, it breaks the app. With numbers as keys, the only way to break the app is to change the order of parameters (and it's already considered a BC break).

@fabpot
Copy link
Member

fabpot commented Feb 15, 2016

👍 for argument indexes. That's already how we manage arguments internally by the way (replaceArgument()).

@linaori
Copy link
Contributor

linaori commented Feb 15, 2016

Hence my original suggestion, as it's simply mapped and you can use replaceArgument($number, $argument), it will be the least effort and the most intuitive.

@weaverryan
Copy link
Member Author

Ok then with arguments by index! Actually, I thought that this would already work - I tried that originally and then opened this "bug" (see my original code block, it matches the last one from @dunglas) exactly.

So, this is "actionable" - someone just needs to make wiring work with a specific index.

Thanks!

@weaverryan
Copy link
Member Author

PR at #17876

weaverryan added a commit to weaverryan/symfony that referenced this issue Feb 22, 2016
weaverryan added a commit to weaverryan/symfony that referenced this issue Feb 29, 2016
fabpot added a commit that referenced this issue Mar 1, 2016
… are set (weaverryan)

This PR was merged into the 2.8 branch.

Discussion
----------

[DependencyInjection] Fixing autowiring bug when some args are set

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #17724, #17878
| License       | MIT
| Doc PR        | todo

This fixes #17724 & #17878.

**#17724**

I've set this against the 2.8 branch because imo it's a bug fix. The [test](https://github.com/symfony/symfony/compare/2.8...weaverryan:auto-wiring-individuals?expand=1#diff-d124c3d39cd5f7c732fb3d3be7a8cb42R298) illustrates the bug - having *some* arguments set beforehand caused auto-wired arguments to be set on the wrong index.

**#17878**

I've also included this fix just to get all the weird ordering problems taken care of at once. I don't think this is a behavior change - autowiring with scalars only worked previously if the argument was optional (still works now) or if you specified that argument explicitly (still works). Otherwise, your argument ordering would have gotten messed up.

Commits
-------

260731b minor changes
865f202 [#17878] Fixing a bug where scalar values caused invalid ordering
cf692a6 [#17724] Fixing autowiring bug where if some args are set, new ones are put in the wrong spot
@fabpot fabpot closed this as completed Mar 1, 2016
fabpot added a commit that referenced this issue Mar 1, 2016
* 2.8:
  fixed issue with PHP 5.3
  The WebProcessor now forwards the client IP
  minor changes
  [#17878] Fixing a bug where scalar values caused invalid ordering
  [#17724] Fixing autowiring bug where if some args are set, new ones are put in the wrong spot
  bumped Symfony version to 2.3.39
  updated VERSION for 2.3.38
  update CONTRIBUTORS for 2.3.38
  updated CHANGELOG for 2.3.38
fabpot added a commit that referenced this issue Mar 1, 2016
* 3.0:
  fixed issue with PHP 5.3
  The WebProcessor now forwards the client IP
  minor changes
  [#17878] Fixing a bug where scalar values caused invalid ordering
  [#17724] Fixing autowiring bug where if some args are set, new ones are put in the wrong spot
  bumped Symfony version to 2.3.39
  updated VERSION for 2.3.38
  update CONTRIBUTORS for 2.3.38
  updated CHANGELOG for 2.3.38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants