Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[DI] Service decoration: autowire the inner service#25631
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
Uh oh!
There was an error while loading.Please reload this page.
Conversation
fdf91e0 to8b75121Compare| if (null !==$innerIndex) { | ||
| // There is more than one argument of the type of the decorated class | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Maybe this case should result in an exception with helpful feedback for the developer. The developer obviously tried to autowire the decorator, so I think we should tell them why it fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It would be a BC break: it currently tries to autowire these services "the regular way", if we throw an exception, it would not be the case anymore.
derrabus commentedDec 30, 2017
Good idea. I needed that feature recently. |
linaori commentedDec 30, 2017
Oh this is a nice improvement! But what about the following?
Often enough I decorate because of logging or caching, which would still make me configure everything. In your commit it does seem to work though, or am I mistaken?https://github.com/symfony/symfony/pull/25631/files#diff-0cd60484959ffb82f3498fcc8bdcac11R21 |
dunglas commentedDec 30, 2017
@iltar I mean: // This is handledclass BarDecoratorimplements BarInterface{publicfunction__construct(LoggerInterface$logger,BarInterface$decorated) { }}// This is ignoredclass BarDecoratorimplements BarInterface{publicfunction__construct(BarInterface$decorated,BarInterface$anotherBar) { }} |
linaori commentedDec 30, 2017
Ah okay, so I just misunderstood your sentence! In that case, big fat 👍 ! |
| } | ||
| if (null !==$innerIndex) { | ||
| $definition->setArgument($innerIndex,newReference($renamedId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
perhaps use aTypedReference?
nicolas-grekas commentedDec 30, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I really like the idea. |
dunglas commentedDec 30, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@nicolas-grekas, good idea I'll try that. The only difference I can see is this case: class BarDecoratorimplements BarInterface{publicfunction__construct(BarInterface$decorated,BarInterface$anotherBar) { }} With the current implementation, it's ignored (and I think it's the right thing to do), with bindings, the decorated service will be injected in both parameters. IMO it's an edge case, if we're fine with that, I'll update the code. |
dunglas commentedDec 30, 2017
In fact it's not possible to use bindings because they exact match the type. Here we need to use |
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Minor CS comments. This misses checking for@required setters, where other passes deal with it AFAIK. Should maybe be fixed.
| usePsr\Log\LoggerInterface; | ||
| /** | ||
| * @author Kévin Dunglas <dunglas@gmail.com> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Not sure about this line, that's a fixture :)
| privatefunctionautowire(ContainerBuilder$container,Definition$definition,string$renamedId):void | ||
| { | ||
| if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
CS wise I think we prefer putting the next line on this one
| !$definition->isAutowired() || | ||
| null === ($innerClass =$container->findDefinition($renamedId)->getClass()) || | ||
| !($reflectionClass =$container->getReflectionClass($definition->getClass())) || | ||
| !$reflectionMethod =$reflectionClass->getConstructor() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
$constructor?
| $innerIndex =null; | ||
| foreach ($reflectionMethod->getParameters()as$index =>$parameter) { | ||
| if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Same CS comment
dunglas commentedDec 30, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Actually I omitted setters willingly. Setter injection is sometime legit, but for a decorator it's more than weird to inject the decorated service this way. I think we should only support constructors (if someone has this specific use case, he can still use manual wiring). |
aaddb17 to3e06dd4Comparenicolas-grekas commentedDec 31, 2017
Seems arbitrary to me, and inconsistent, we should support setters everywhere IMHO. |
dunglas commentedDec 31, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Ok I'll add support for setters, it cannot hurt if you don't use them :) |
dunglas commentedFeb 5, 2018
@Tobion this PR changes nothing regarding service decoration. It will work as excepted. |
dunglas commentedFeb 6, 2018
@chalasr I added support for renamed id in an easy but a bit hacky way. WDYT? |
chalasr commentedFeb 10, 2018
@dunglas Looks good enough to me. |
dunglas commentedFeb 13, 2018
@chalasr AFAIK, this PR doesn't change anything to this behavior. |
ead558c toecd14aaComparedunglas commentedMar 16, 2018
Failures not related, ping @symfony/deciders. It would be great to have it in 4.1. |
javiereguiluz left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
DX-wise this is fantastic! I love it ... but I left a minor comment.
| * | ||
| * Used to store the name of the renamed id when using service decoration together with autowiring | ||
| */ | ||
| public$previousRenamedId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The name of this property is confusing to me:previousRenamedId "previous" and "renamed" together is confusing: is this the previous ID before the renaming? Is this the new renamed ID different from the previous one? Is this the first renamed ID and now we are doing the second renaming (so this is the "previous rename"? etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think it's a rest of the previous implementation (whererenamedId was already used). ispreviousrenamedId ok to you?
javiereguiluzMar 16, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It depends on what this property really is (sorry, but its PHPdoc is confusing to me too). Here are some alternative proposals:
$decoratedServiceOriginalId$decoratedServiceNewId$decoratedServiceId$innerServiceId$decoratingServiceId- ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I agree the name is confusing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Done (I pickedinnerServiceId). Is it good for you guys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Much better. Thanks!
chalasr left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
👍
fabpot left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
with minor comments
| * added support for variadics in named arguments | ||
| * added PSR-11`ContainerBagInterface` and its`ContainerBag` implementation to access parameters as-a-service | ||
| * added support for autowiring to service's decorators |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
added support for service's decorators autowiring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
done
| /** | ||
| * @internal | ||
| * | ||
| * Used to store the name of the renamed id when using service decoration together with autowiring |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
renamed -> inner?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
done
fabpot commentedMar 20, 2018
Thank you@dunglas. |
…bbuh)This PR was merged into the 4.1-dev branch.Discussion----------[DependencyInjection] fix expected exception message| Q | A| ------------- | ---| Branch? | master| Bug fix? | yes| New feature? | no| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets || License | MIT| Doc PR |Updates a test that was introduced in#25631 to match the changes made in#26595.Commits-------042eb4f fix expected exception message
This PR was merged into the 4.1 branch.Discussion----------[DI] Fix autowire inner service| Q | A| ------------- | ---| Branch? | 4.1| Bug fix? | yes| New feature? | no| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets |#25631| License | MIT| Doc PR | -This PR fix multiple levels of decoration. Unfortunately, this [good question](#25631 (comment)) in origin PR has not been heard 🎧 😄.@dunglas@chalasrCommits-------b79d097 [DI] Fix autowire inner service
This PR was merged into the 4.1 branch.Discussion----------[DI] Fix autowire inner service| Q | A| ------------- | ---| Branch? | 4.1| Bug fix? | yes| New feature? | no| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | #25631| License | MIT| Doc PR | -This PR fix multiple levels of decoration. Unfortunately, this [good question](symfony/symfony#25631 (comment)) in origin PR has not been heard 🎧 😄.@dunglas@chalasrCommits-------b79d097c2a [DI] Fix autowire inner service
Uh oh!
There was an error while loading.Please reload this page.
Try to automatically inject the decorated service.
Before:
After:
To trigger the autowiring, the following conditions must be met: