-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DependencyInjection] Add #[TaggedItem]
attribute for defining the index and priority of classes found in tagged iterators/locators
#40248
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
#[Service]
attribute on PHP 8#[Service]
attribute on PHP 8
#[Service]
attribute on PHP 8#[Service]
attribute on PHP 8
ed865ff
to
635fee7
Compare
Hey! I appreciate you submitting this PR. I think @daniel-iwaniec has recently worked with this code. Maybe they can help review this? Cheers! Carsonbot |
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.
Looks good, thanks!
src/Symfony/Component/DependencyInjection/Compiler/RegisterAutoconfigureAttributesPass.php
Outdated
Show resolved
Hide resolved
#[Service]
attribute on PHP 8#[Service]
attribute on PHP 8
Any comment here? /cc @symfony/mergers |
Will this mean that any class with Example: services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*' The DI only cares about classes in the |
This is read only for autoconfigured services. Loading services is not affected by the annotation. |
Cool. So this PR just adds support for another way to define services. PHP, Yaml, XML and PHP8 annotations. I would like to see this feature. I find it useful to get an easy way to prioritise tagged services. 👍 |
An How is this different from e.g. #34095 (comment)? Also, having yet another way to configure services feels too much to me. I'm sorry, but I'm 👎 for this as-is. |
Argh, please, reconsider. I already recorded my talk about new feats in 5.3, because this one makes just so much sense! How does this differ from #34095 (comment)? Exactly like #39776: because it is opt-in and bound to autoconfiguration. This attribute is the only elegant way to improve the ugly We cannot not merge this (or a variant of it). |
Thanks for adding some detailed context on the scope of this attribute Nicolas!
To me, it seems like it's doing too many things at once (and e.g. the "name" argument has multiple meanings). This also makes the Would it make sense to create an attribute for each use-case?
|
@chalasr if I understand correctly, there is a huge difference: the service isn't registered by the attribute, but only configured by it. The YAML still drives the loading, whereas in your mentioned proposal, the author was talking about registration of service. Generally speaking, my main concerns regarding attributes like these is to be clear that they don't register but configure things. Basically, they are (and should stay) hints for the DI container, like an implemented interface would be (Twig ExtensionInterface). Perhaps is the "Service" attribute name misleading in that regard? |
That is worst to me, it's even more complex to understand and explain.
Yes, I think so. |
I see your point and I agree then. But I do think this idea make a lot of sense, if the wording was improved. |
|
In the description, I didn't mention the part related to the "id" until the last sentence: |
I don't think there is a need to discuss in over-exaggerated terms. In #39776 (comment) , we established that attribute names should be crystal clear about their meaning and function in their name. I think there is, at least for the tagged features, a consensus that attributes are a better replacement for the static methods we currently use. The only thing there is no consensus about is the name of the attribute. I think it makes sense to see what other naming alternatives we have. E.g. the static methods both include "default" ( Personally, I feel like that is still not crystal clear. I would be in favor of also mentioning its purpose: default values when used with the tagged features. |
Naming things is always hard. 🙂 |
As my understanding becomes clearer thanks to your comments, I'd say this attribute is meant to declare how a service should be named when it is part of a collection of siblings. I allowed adding a type so that the name could vary by type, when a class implements many base types and is part of many collections, one for each such type. Declaring a name when part of a collection allows several use cases. We identified 3 of them: key in an iterator, id in a locator, and name for an autowiring alias. There could be more use cases, that's the point of attributes - being decoupled from their use cases. For the named autow alias use case, we need an interface to create them. If the attribute doesn't declare the type, I don't know which interface I should prefix to the name. Taking all supertypes would look wrong to me. Maybe we can also drop this named autow alias part (alongside with dropping the "id" part). But I don't see anything inherently wrong with generating these aliases - quite the contrary. |
About naming, we have already made some decisions:
About using Talking about About
Actually yes, I do have one: |
but any class registered in the container is used a a service. Regarding defining named autowiring aliases, I'm wondering about the usefulness. In my experience, the main benefit of named autowiring aliases (over normal autowiring aliases) is when you register multiple instances of your class in the container (generally with different config in them). And in that case, you cannot rely on autoconfiguration anyway (as you cannot autoconfigure them in different ways as they will have the same attributes for both instances of the same class). |
In his example, he would use several loggers and a single LoggerInterface type, thus a default name for the autowiring aliases on the children classes. I do think it makes sense there. |
#[Service]
attribute on PHP 8#[TaggedItem]
attribute for defining the index and priority of classes found in tagged iterators/locators
6163a20
to
ecdb39b
Compare
I think I found the way to go! |
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 love this change! This is configuration that is in the PHP code anyways, and an attribute is much cleaner than 2 static methods. Thanks for reconsidering this PR Nicoals.
(no github approval as I can't say anything meaningful about the changes in the compiler pass)
src/Symfony/Component/DependencyInjection/Attribute/TaggedItem.php
Outdated
Show resolved
Hide resolved
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 comment - I love the new name and scope of this PR!
src/Symfony/Component/DependencyInjection/Attribute/TaggedItem.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php
Outdated
Show resolved
Hide resolved
ecdb39b
to
7eb6808
Compare
Thank you all for the review and the discussion, as always we've made a useful turn towards the better. I've now updated the implementation to make this a strict replacement for the static methods. No more "type" property anymore, this is strictly a |
src/Symfony/Component/DependencyInjection/Tests/Compiler/PriorityTaggedServiceTraitTest.php
Show resolved
Hide resolved
…index and priority of classes found in tagged iterators/locators
7eb6808
to
252f2ca
Compare
… (nicolas-grekas) This PR was merged into the 5.3-dev branch. Discussion ---------- [DependencyInjection] accept null index in #[TaggedItem] | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - As hinted by @stof in #40248 (comment) Commits ------- 6d16fac [DI] accept null index in #[TaggedItem]
I miss that we lost the ability to define a custom priority method or an index method with attributes. Sometimes is usefull to use some logic there, which can't be done in attribute argument. For example this case: abstract class AbstractFixtures implements FixturesInterface
{
private static int $defaultPriority = -1;
public static function getDependencies(): array
{
return [];
}
public static function getPriority(): int
{
$priority = self::$defaultPriority;
foreach (static::getDependencies() as $dependency) {
$priority += $dependency::getPriority();
}
return $priority;
}
}
final class ArticleFixtures extends AbstractFixtures
{
public static function getDependencies(): array
{
return [UserFixtures::class, RubricFixtures::class];
}
} Or did I miss something? I know I can still use methods |
@marforon the name of the methods are customizable by the place creating a ServiceLocatorArgument, not by the places being referenced in it, which is exactly how it works without using attributes too. |
@stof can be those default methods customized by only using attributes? App\DataFixtures\FixturesLoader:
arguments:
$fixtures: !tagged_iterator
tag: 'app.fixtures'
index_by: 'key'
default_index_method: 'getIndexKey'
default_priority_method: 'getPriority'
|
@marforon that's expected, because |
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()
andgetDefaultPriority()
methods that ppl could use for this purpose:This will ship the corresponding service at index
api.logger
, priority=123 when building locators/iterators.