-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DI] Replace wildcard-based methods autowiring by @required
annotation
#21763
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
Conversation
I like it! It removes 2 things I don't like:
Yes! I agree - autowiring should do as little as possible (based on the code you've written). And explaining autowiring should now be pretty simple!
|
I like the autowire feature, but I don't like this proposal. Our company has no annotations policy, so if I understand correctly this means no autowire for us. |
Some of my first thoughts :) #19631 (comment) i think it's a good convention 👍
With named arguments we could define optional ones, override required ones, and let autowiring fill in the remaining required ones.. right? And shouldnt this be allowed by the annotation-form as well? I.e. |
I see |
@mvrhov I think you did not understand correctly: if you don't want to use the annotation, that won't prevent you from using autowiring. First, constructor autowiring doesn't require it. Then, for setters and getters, that will just make you declare which of them to autowire in the DI config, instead of in the code. It has to be somewhere. The annotation allows code authors to help autowiring users so that they can save these DI config lines. Only that.
@ro0NL Right!
Yes, this shouldn't be allowed, because this is moving the DI configuration right into the code - which is not what this PR does - and it a totally different topic.
Same here, we shouldn't go that way to me, too much added complexity for no benefit at all. |
I will see a lot of people remove
|
83b96c3
to
f286fcc
Compare
First of all, I'm really happy that we will remove the That being said, having "something" to autowire dependencies in a lazy-way would be a great feature for Symfony 3.3. And we are almost there. I've migrated several projects and implemented all the new features of the container, and I have to say that this is really a joy to work with (I actually encourage anyone to try it on their projects and give feedback). The proposed If we look at the semantic of the proposed Those annotations gather generic and purely descriptive semantic about some methods/classes, they have nothing specific about Symfony and can/could be used by any PHP code. Note that we use the semantic they convey in the Debug component, in DebugClassLoader, to give a better DX, so we have a precedent here. I think all of this applies also to the The fact that this annotation is not yet standardized shouldn't prevent us from adopting it (we did so for This is also very different from previous proposals that tried to move configuration into annotations. Using the |
👍 |
Thank you @nicolas-grekas. |
…quired` annotation (nicolas-grekas) This PR was squashed before being merged into the 3.3-dev branch (closes #21763). Discussion ---------- [DI] Replace wildcard-based methods autowiring by `@required` annotation | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no (affects things that are only on master) | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - While playing a bit with new features in master around DI configuration, several people around me got bitten by wildcard-based autowiring. The typical example is adding `autowire: [set*]` in `_defaults`: use that on `resource: ../src/Command/` PSR4-based loading and boom, `setApplication` and `setHelperSet` will now be wrongly called. You could tell me "of course, don't to that" - but being bitten so early on a master-only feature makes me really unconfident that this will be easy enough for people after the release. If wildcard-based autowiring is removed, then I don't see anymore the need for allowing arrays as in `autowire: [setFoo,getBar]`. Moreover, this array syntax has a core DX issue: it's a dead end as far as the learning curve is concerned. You learn it, then when becoming a more advanced dev, someone teaches you that you'd better use another syntax: explicit wiring. And in fact, we don't need it at all, because something else already exists: just declare a method call, but don't define its arguments. If `autowire: true` is set, then the AutowiringPass already fills in the holes. There is only one tweak required to make this work: don't autowire optional arguments for method calls - or that'd be a BC break. To my PoV that's even better: this makes autowiring fit a "do the minimum to make it work" strategy. A really good one to me. But there is still an issue: wildcard-based autowiring fits a need. Namely, it allows one to define a convention (eg. `'set*'`), and have all such methods that follow the convention be autowired. To me, this looks like doing it reverse (the DI config should adapt to the code, not reverse). So, to fill this need, let the declaration be in the source: just use an annotation! This PR adds support for the `@required` annotation, borrowed from the Spring framework: https://www.tutorialspoint.com/spring/spring_required_annotation.htm Using the annotation is totally optional of course. If you do, *and if autowiring is on*, then it'll be autowired. If you don't, nothing changes: do manual wiring. Even when not using autowiring, the annotation is still a nice hint for the consumer of your classes: it tells the reader that this method needs to be called for correct instantiation - thus lowering one drawback of setter injection (discoverability). The implementation of the annotation parsing is done using a few regexp (no dep on any complex parser) - and works with inheritance, by leveraging the `@inheritdoc` tag (the default behavior being to *not* inherit anything from parent methods). All in all, looking at the diff stats, it makes everything simpler. Good sign, isn't it? Commits ------- f286fcc [DI] Replace wildcard-based methods autowiring by `@required` annotation 9081699 Revert "minor #21315 [DI][FrameworkBundle] Show autowired methods in descriptors (ogizanagi)"
Too late but 👍 too, definitely better than |
Playing with this now, there is one catch, it does not play well with Doctrine Annotations, which wants to parse everything. So, we need to add: \Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('required'); |
public function setFoo(Foo $foo) | ||
{ | ||
// should be called | ||
} | ||
|
||
/** @inheritdoc*/ |
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 lacks a test for a child method with no dock block and a parent method marked with @required
.
Does this mean setter autowiring is no longer possible with |
of course not, nothing changed on that side :) |
oh sorry, too fast! maybe add the annotation to the trait for such cases? would you like to submit a PR? |
The issue is the setter's parameter is optional. https://github.com/symfony/symfony/blob/master/src/Symfony/Component/DependencyInjection/ContainerAwareTrait.php#L31 |
Sure, then it's a yes, but I don't see this as a limitation. Use instanceof conditionals instead |
I got it working with |
Next step could be implementing ServiceSubscriberInterface :) see #21708 |
Haha neat, thanks! This autowiring stuff is moving fast! :) |
While playing a bit with new features in master around DI configuration, several people around me got bitten by wildcard-based autowiring. The typical example is adding
autowire: [set*]
in_defaults
: use that onresource: ../src/Command/
PSR4-based loading and boom,setApplication
andsetHelperSet
will now be wrongly called. You could tell me "of course, don't to that" - but being bitten so early on a master-only feature makes me really unconfident that this will be easy enough for people after the release.If wildcard-based autowiring is removed, then I don't see anymore the need for allowing arrays as in
autowire: [setFoo,getBar]
. Moreover, this array syntax has a core DX issue: it's a dead end as far as the learning curve is concerned. You learn it, then when becoming a more advanced dev, someone teaches you that you'd better use another syntax: explicit wiring.And in fact, we don't need it at all, because something else already exists: just declare a method call, but don't define its arguments. If
autowire: true
is set, then the AutowiringPass already fills in the holes. There is only one tweak required to make this work: don't autowire optional arguments for method calls - or that'd be a BC break. To my PoV that's even better: this makes autowiring fit a "do the minimum to make it work" strategy. A really good one to me.But there is still an issue: wildcard-based autowiring fits a need. Namely, it allows one to define a convention (eg.
'set*'
), and have all such methods that follow the convention be autowired. To me, this looks like doing it reverse (the DI config should adapt to the code, not reverse). So, to fill this need, let the declaration be in the source: just use an annotation!This PR adds support for the
@required
annotation, borrowed from the Spring framework:https://www.tutorialspoint.com/spring/spring_required_annotation.htm
Using the annotation is totally optional of course. If you do, and if autowiring is on, then it'll be autowired. If you don't, nothing changes: do manual wiring.
Even when not using autowiring, the annotation is still a nice hint for the consumer of your classes: it tells the reader that this method needs to be called for correct instantiation - thus lowering one drawback of setter injection (discoverability).
The implementation of the annotation parsing is done using a few regexp (no dep on any complex parser) - and works with inheritance, by leveraging the
@inheritdoc
tag (the default behavior being to not inherit anything from parent methods).All in all, looking at the diff stats, it makes everything simpler. Good sign, isn't it?