Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[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

Merged
nicolas-grekas merged 1 commit intosymfony:7.3fromGromNaN:tags-excluded
Feb 11, 2025

Conversation

GromNaN
Copy link
Member

@GromNaNGromNaN commentedFeb 5, 2025
edited by nicolas-grekas
Loading

QA
Branch?7.3
Bug fix?no
New feature?yes
Deprecations?no
Issues-
LicenseMIT

We couldnot use the methodfindTaggedServiceIds 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 aAppModel attribute class and use it on any class of the project.

In the extension class:

$this->registerAttributeForAutoconfiguration(AppModel::class,staticfunction (ChildDefinition$definition) {$definition->addExcludedTag('app.model');});

In a compiler pass:

$classes = [];foreach($containerBuilder->findExcludedServiceIds('app.model')as$id =>$tags) {$classes[] =$containerBuilder->getDefinition($id)->getClass();}$containerBuilder->setParameter('.app.model_classes',$classes);

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.

@carsonbotcarsonbot added this to the7.3 milestoneFeb 5, 2025
@GromNaNGromNaN changed the title[DependencyInjection] Accept excluded tags infindTaggedServiceIds, with a new parameter[DependencyInjection] Accept excluded services infindTaggedServiceIds, with a new parameterFeb 5, 2025
@GromNaNGromNaN changed the title[DependencyInjection] Accept excluded services infindTaggedServiceIds, with a new parameter[DependencyInjection] Return excluded services infindTaggedServiceIds, with a new parameterFeb 5, 2025
Copy link
Member

@nicolas-grekasnicolas-grekas left a 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)

GromNaN reacted with thumbs up emoji
@GromNaNGromNaN changed the title[DependencyInjection] Return excluded services infindTaggedServiceIds, with a new parameter[DependencyInjection] AddContainerBuilder::findTaggedValueClasses() for auto-discovering value-object classesFeb 5, 2025
@GromNaN
Copy link
MemberAuthor

I added the method, that's a lot better and it allows to add the additional feature of automatically set thecontainer.excluded tag. But isn't it late in the CompilerPass workflow?

Copy link
Member

@nicolas-grekasnicolas-grekas left a 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.

@nicolas-grekas
Copy link
Member

nicolas-grekas commentedFeb 6, 2025
edited
Loading

But isn't it late in the CompilerPass workflow?

I think I've got your point. A complimentary idea might be to addDefinition::tagAsValueObject(), to be used inregisterAttributeForAutoconfiguration().

Tentatively:

/** * @return $this */publicfunctiontagAsValueObject(string$name,array$attributes = []):static{return$this->addTag($name,$attributes)->addTag('container.excluded', ['source' =>\sprintf('by tag "%s"',$name));}

Copy link
Member

@nicolas-grekasnicolas-grekas left a 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 :)

@GromNaN
Copy link
MemberAuthor

GromNaN commentedFeb 6, 2025
edited
Loading

Perfect, we have the full feature like this:

  • Definition::tagAsValueObject() called inside aregisterAttributeForAutoconfiguration
  • ContainerBuilder::findTaggedValueObjects() called inside a compiler pass

Now I wonder if we could skip de tag and delay theregisterAttributeForAutoconfiguration callback to any of the compile time. With something likeregisterAttributeForValueObject()

functionregisterAttributeForValueObject(Entity::class, staticfunction (ContainerBuilder$container,array$classes) {$container->setParameter('doctrine.entity_classes',$classes);});

@nicolas-grekasnicolas-grekas changed the title[DependencyInjection] AddContainerBuilder::findTaggedValueClasses() for auto-discovering value-object classes[DependencyInjection] AddDefinition::addValueObjectTag() andContainerBuilder::findTaggedValueObjects() for auto-discovering value-objectsFeb 6, 2025
@chalasr
Copy link
Member

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.

yceruto reacted with thumbs up emoji

@GromNaN
Copy link
MemberAuthor

GromNaN commentedFeb 7, 2025
edited
Loading

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 renameaddValueObjectTag toaddClassTag, andfindTaggedValueObjects tofindTaggedClasses? Or maybeaddExcludedClassTag to be explicit that we also exclude the class from the DIC.

Then we could have a!tagged_classes in Yaml to automatically inject class names into a service, in the same format asfindTaggedClasses.

ruudk reacted with thumbs up emoji

@nicolas-grekas
Copy link
Member

nicolas-grekas commentedFeb 7, 2025
edited
Loading

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:

addExcludingTag(string $name, array $attributes = [])

findExcludedServiceIds(string $name) (and we remove the autoexclude argument now that the name contains the term "exclude" - or keep it, and throw an exception when its false and a matching definition doesn't have the container.excluded tag?)

@GromNaN
Copy link
MemberAuthor

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$containerBuilder->getDefinition($serviceId)->getClass() in the loop in the compiler pass.

@nicolas-grekas
Copy link
Member

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.

@GromNaN
Copy link
MemberAuthor

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
Copy link
Member

nicolas-grekas commentedFeb 7, 2025
edited
Loading

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
Copy link
Member

chalasr commentedFeb 7, 2025
edited
Loading

That's class definitions that contribute to the build of the DIC; even if this classes are not used for services.

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.

We are creating a way to read attributes on classes

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.

If VO doesn't match, then what remains is that we want to exclude those definitions

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.

nicolas-grekas added a commit that referenced this pull requestFeb 10, 2025
…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
@GromNaN
Copy link
MemberAuthor

I updated the methods with more generic names:Definition::addExcludeTag() andContainerBuilder::findExcludedServiceIds($tagName).

findExcludedServiceIds throws an exception when a service as the searched tag but notcontainer.excluded.

@GromNaNGromNaNforce-pushed thetags-excluded branch 2 times, most recently from6cedb37 tof2259e1CompareFebruary 11, 2025 10:55
Copy link
Member

@nicolas-grekasnicolas-grekas left a 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.

@GromNaNGromNaN changed the title[DependencyInjection] AddDefinition::addValueObjectTag() andContainerBuilder::findTaggedValueObjects() for auto-discovering value-objects[DependencyInjection] AddDefinition::addExcludedTag() andContainerBuilder::findExcludedServiceIds() for auto-discovering value-objectsFeb 11, 2025
…erBuilder::findExcludedServiceIds()` for auto-discovering value-objects
@nicolas-grekas
Copy link
Member

Thank you@GromNaN.

GromNaN reacted with hooray emoji

@nicolas-grekasnicolas-grekas merged commit09ba274 intosymfony:7.3Feb 11, 2025
9 of 11 checks passed
@GromNaNGromNaN deleted the tags-excluded branchFebruary 11, 2025 13:20
nicolas-grekas added a commit that referenced this pull requestMar 20, 2025
…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"
@fabpotfabpot mentioned this pull requestMay 2, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@OskarStarkOskarStarkOskarStark left review comments

@alexandre-dauboisalexandre-dauboisalexandre-daubois left review comments

@nicolas-grekasnicolas-grekasnicolas-grekas approved these changes

@chalasrchalasrchalasr approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
7.3
Development

Successfully merging this pull request may close these issues.

6 participants
@GromNaN@nicolas-grekas@chalasr@OskarStark@alexandre-daubois@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp