Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.6k
[DependencyInjection] AddDefinition::addExcludedTag()
andContainerBuilder::findExcludedServiceIds()
for auto-discovering value-objects#59704
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
Conversation
findTaggedServiceIds
, with a new parameterfindTaggedServiceIds
, with a new parameterfindTaggedServiceIds
, with a new parameterfindTaggedServiceIds
, with a new parameterThere 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'm not sure I like to have a method with "services" in its name return non-services things
this made me wonder if we should add another method instead like this?
findTaggedValueObjects($name, $autoExclude = true)
findTaggedServiceIds
, with a new parameterContainerBuilder::findTaggedValueClasses()
for auto-discovering value-object classesI added the method, that's a lot better and it allows to add the additional feature of automatically set the |
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.
But isn't it late in the CompilerPass workflow?
This depends on the stage the compiler pass runs, right?
Nothing related to this PR IIUC.
src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
nicolas-grekas commentedFeb 6, 2025 • 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 think I've got your point. A complimentary idea might be to add Tentatively: /** * @return $this */publicfunctiontagAsValueObject(string$name,array$attributes = []):static{return$this->addTag($name,$attributes)->addTag('container.excluded', ['source' =>\sprintf('by tag "%s"',$name));} |
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.
Closer to the sweet spot :)
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
GromNaN commentedFeb 6, 2025 • 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.
Perfect, we have the full feature like this:
Now I wonder if we could skip de tag and delay the functionregisterAttributeForValueObject(Entity::class, staticfunction (ContainerBuilder$container,array$classes) {$container->setParameter('doctrine.entity_classes',$classes);}); |
ContainerBuilder::findTaggedValueClasses()
for auto-discovering value-object classesDefinition::addValueObjectTag()
andContainerBuilder::findTaggedValueObjects()
for auto-discovering value-objectsUh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
I get and support the use case this tries to solve, but I don't like the fact we are adding the concept of value objects to the DIC. Services vs non-services is all the container knows so far which makes sense. Also good part of the objects mentioned in the linked use cases do not match the definition of a value object actually: neither entity/models nor API resources are VO, both have identifiers. |
Uh oh!
There was an error while loading.Please reload this page.
GromNaN commentedFeb 7, 2025 • 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.
That's class definitions that contribute to the build of the DIC; even if this classes are not used for services. What do you think if we rename Then we could have a |
nicolas-grekas commentedFeb 7, 2025 • 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 don't like addClassTag / findTaggedClasses - it doesn't tell anything about those not being services. Also this returns identifiers, not classes (even if most of the time we equal both). If VO doesn't match, then what remains is that we want to exclude those definitions. What about:
|
Since it's the class names we're interested in here, we can group the result tags by class name and not by serviceId. This way, there's no need to call |
Class names are only one possible use case. Maybe the main one, but I don't see why we should optimize the design for this use case. |
We are creating a way to read attributes on classes and make this metadata available to inject in services. There is no point in having multiple definitions for the same class as attributes are defined on the class itself (we can merge them). |
nicolas-grekas commentedFeb 7, 2025 • 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.
Unless there is one. My point is that the design and the code are perfectly able to handle more than just lists of classes, and I don't see any reasons (but our current narrow vision) to restrict the capabilities of what we already have... |
chalasr commentedFeb 7, 2025 • 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.
A DIC is all about services. The concept of excluded services has been added to Symfony's DIC mostly for DX purpose following the introduction of autowiring/autodiscovery, and it is still mostly hidden today if we look at the component's public API.
Fact is that DI's low-level API is decoupled from classes through supporting any string as service identifier everywhere and allowing callables/factories for service construction, which is nice and fits PSR-11 perfectly also.
I agree. Trying to find a generic term for groupingsome classes through the container then making them excluded looks like a dead end as there are many possible reasons for a class not to be registered as service and certainly ones we don't even imagine. Excluded services however is a concept we already have so let's build on it. Then Nicolas' proposal looks sensible. |
…constructor when autodiscovering (nicolas-grekas)This PR was merged into the 7.3 branch.Discussion----------[DependencyInjection] Don't skip classes with private constructor when autodiscovering| Q | A| ------------- | ---| Branch? | 7.3| Bug fix? | no| New feature? | yes| Deprecations? | no| Issues |Fix#48392| License | MITWith value objects auto-discovery becoming more mainstream (see#59704), it's time to fix registering classes with private constructors.Those are skipped today but with support for `#[Autoconfigure(constructor: 'createInstance')]` as introduced in#49665, this doesn't make sense anymore.Best reviewed [ignoring whitespace](https://github.com/symfony/symfony/pull/59712/files?w=1).Commits-------99830f6 [DependencyInjection] Don't skip classes with private constructor when autodiscovering
I updated the methods with more generic names:
|
6cedb37
tof2259e1
CompareThere 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.
LGTM, just minor wording things.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Definition::addValueObjectTag()
andContainerBuilder::findTaggedValueObjects()
for auto-discovering value-objectsDefinition::addExcludedTag()
andContainerBuilder::findExcludedServiceIds()
for auto-discovering value-objectsUh oh!
There was an error while loading.Please reload this page.
…erBuilder::findExcludedServiceIds()` for auto-discovering value-objects
a02b876
to7a0443b
CompareThank you@GromNaN. |
09ba274
intosymfony:7.3Uh oh!
There was an error while loading.Please reload this page.
…tag" (kbond)This PR was merged into the 7.3 branch.Discussion----------[DependencyInjection] Rename "exclude tag" to "resource tag"| Q | A| ------------- | ---| Branch? | 7.3| Bug fix? | no| New feature? | no| Deprecations? | no| Issues | Follow up to#59704| License | MITI find `$definition->addExcludedTag('app.model')` and `$containerBuilder->findExcludedServiceIds('app.model')` unintuitive. If feels like your excluding something from the DI container but in fact, your registering it, but in a "different way". The fact that it's an excluded service is just a side-effect. This is especially weird when the tag has attributes (`$definition->addExcludedTag('app.model', ['connection' => 'default'])`).Totally open for a name other than "resource".Commits-------aa91936 [DI] Rename "exclude tag" to "resource tag"
Uh oh!
There was an error while loading.Please reload this page.
We couldnot use the method
findTaggedServiceIds
in#59401 (comment), same forapi-platform/core#6943.As "using the container loading tools to do resource discovery quite seamlessly"seems to be a good idea, this changes make it easier.
I'm not closed to alternative ideas if we want to go further with this use-case.
Usage
Let's create a
AppModel
attribute class and use it on any class of the project.In the extension class:
In a compiler pass:
And this parameter can be injected into a service, or directly update a service definition to inject this list of classes. The attribute parameters can be injected into the tag, and retrieved in the compiler pass, for more advanced configuration.