-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DependencyInjection] Add #[Autoconfigure]
to help define autoconfiguration rules
#39804
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
src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
Outdated
Show resolved
Hide resolved
8c5ba49
to
1e1b86e
Compare
src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
Outdated
Show resolved
Hide resolved
1e1b86e
to
bd4ece5
Compare
is there any reason for the "auto discovered services only" actually? |
src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
Outdated
Show resolved
Hide resolved
Quick nitpick question: should the attribute be named The recently proposed |
I feel like I missed explaining correctly how this works. Yes, this attribute declares a configuration rule for autoconfiguration. |
#[Autoconfigure]
to help define autoconfiguration rules
bd4ece5
to
ac88c9e
Compare
3a1e8b6
to
5b98e9d
Compare
5b98e9d
to
fdee7f2
Compare
fdee7f2
to
37a5d26
Compare
src/Symfony/Component/DependencyInjection/Compiler/RegisterAutoconfigureAttributesPass.php
Show resolved
Hide resolved
IIUC, we now have 2 competing PRs here. As far as I know, it was decided that progress continues in #39897? Please correct me if I'm wrong, but otherwise this one should be closed I think. |
@wouterj this one provides something else. Both should be merged to me in the end. This one before #39897 since it's ready and might be used by #39897 as explained in #39897 (comment) |
afe384e
to
e66a3ba
Compare
/cc @symfony/mergers anyone? |
src/Symfony/Component/DependencyInjection/Compiler/RegisterAutoconfigureAttributesPass.php
Show resolved
Hide resolved
As requested, I'll post some of my comment in the other PR (ref: #39897 (comment) ) here: 😃 What I like about this PR is that it reuses the autoconfigure system (using the Yaml file loader seems a bit hacky, but I'm surely not the one to make a decision about that). |
What matters here is how one can describe something using an array data structure. YamlLoader does exactly this: turn arrays (from yaml) into actual calls. Here, we just reuse that logic, so that the same array-structures can also be used in attributes. E.g.:
All ppl that use
There is a critical difference with #39897: the attribute in this PR allows defining rules that are inherited. #39897 defines attributes that are not inherited. That's THE critical difference between both PRs, and why they fill a different need.
Can you clarify? To me, it looks like you're arguing against empowering ppl, which I'm sure you aren't.
I do not understand this "coupling" argument. To me, as I explained in #39776 (comment), there is zero difference between this PR, #39776 or #39897 in this regard. Maybe you can help me understand what you mean with actual examples of when this "coupling" would happen?
See "the critical difference" I mention above. |
e66a3ba
to
c8ace88
Compare
TL;DR of my previous comment:
Note that these two lines are orthogonal. |
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 understand the intention of this generic attribute as a nicer way to configure autoconfiguration rules for userland base types.
Instead of cluttering my kernel with…
$container->registerForAutoconfiguration(MyInterface::class)
->addTag('my_tag');
… I annotate this rule to my interface instead.
#[Autoconfigure(tags: ['my_tag'])]
interface MyInterface {}
Did I get this right?
I think, this is the use case we can agree on. But since attributes are a new feature to most users, it is imperative that we distinguish the use-cases of this PR and #39897 in the documentation.
c8ace88
to
64ab6a2
Compare
@derrabus you've got it right. I agree about the doc. |
…r defining the index and priority of classes found in tagged iterators/locators (nicolas-grekas) This PR was merged into the 5.3-dev branch. Discussion ---------- [DependencyInjection] Add `#[TaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Next to #39804, this PR adds a new `#[TaggedItem]` attribute that ppl can use to define the index of their service classes when they're used in tagged collections (iterators/locators. This replaces the `public static getDefaultName()` and `getDefaultPriority()` methods that ppl could use for this purpose: ```php #[TaggedItem(index: 'api.logger', priority: 123)] class MyApiLogger implements LoggerInterface { } ``` This will ship the corresponding service at index `api.logger`, priority=123 when building locators/iterators. Commits ------- 252f2ca [DependencyInjection] Add `#[TaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators
This is a really cool feature, but I've just tried it and there seems to be an issue: #[Autoconfigure(tags: ['some.tag'])]
interface MyServiceInterface {}
class MyService implements MyServiceInterface {}
$class = new ReflectionClass(MyService::class);
// That's how RegisterAutoconfigureAttributesPass does it
$attributes = $class->getAttributes(Autoconfigure::class, \ReflectionAttribute::IS_INSTANCEOF);
// Whoopsie, empty array
var_dump($attributes); Running PHP 8.0.6. Looks like the |
You might have missed how this works. I can't really help because I don't know what you want todo, but of course, requesting the attributes on class |
@nicolas-grekas Yeah, I might've misunderstood something. The announcement in blog says that So, I've tried this: #[Autoconfigure(tags: ['some.tag'])]
interface ServiceInterface {}
class ServiceA implements ServiceInterface {}
class ServiceB implements ServiceInterface {} services:
_defaults:
autowire: true
autoconfigure: true
App\ServiceA: ~
App\ServiceB: ~ And I was expecting both services to be tagged, but they are not. |
Please open an issue if you think you found a bug, with a reproducer ideally. |
Being inspired by the discussion with @derrabus in #39776.
This PR allows declaring autoconfiguration rules using an attribute on classes/interfaces, eg:
#[Autoconfigure(bind: ['$foo' => 'bar'], tags: [...], calls: [...])]
This should typically be added on a base class/interface to tell how implementations of such a base type should be autoconfigured. The attribute is parsed when autoconfiguration is enabled, except when a definition has the
container.ignore_attributes
tag, which allows opting out from this behavior.As usual, the corresponding rules are applied only to services that have autoconfiguration enabled.
In practice, this means that this enables auto-tagging of all implementations of this interface:
Of course, all auto-configurable settings are handled (calls, bindings, etc.)
This PR adds another attribute:
#[AutoconfigureTag()]
.It extends
#[Autoconfigure]
and allows for specifically defining tags to attach by autoconfiguration.The name of the tag is optional and defaults to the name of the tagged type (typically the FQCN of an interface). This should ease with writing locators/iterators of tagged services.
#[AutoconfigureTag()] interface MyInterface {...}