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

[Validator] Add#[ExtendsValidationFor] to declare new constraints for a class#61545

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
fabpot merged 1 commit intosymfony:7.4fromnicolas-grekas:validator.for
Sep 10, 2025

Conversation

@nicolas-grekas
Copy link
Member

@nicolas-grekasnicolas-grekas commentedAug 28, 2025
edited
Loading

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

This PR builds on#61528

I propose to add a#[ExtendsValidationFor] attribute that allows adding validation constraints to another class.
This is typically needed for third party classes. For context, Sylius has a nice doc about this:
https://docs.sylius.com/the-customization-guide/customizing-validation

At the moment, the only way to achieve this is by declaring the new constraints in the (hardcoded)config/validation/ folder, using either xml or yaml. No attributes.

With this PR, one will be able to define those extra constraints using PHP attributes, set on classes that'd mirror the properties/getters of the targeted class. The compiler pass will ensure that all properties/getters declared in these source classes also exist in the target class. (source = the app's class that declares the new constraints; target = the existing class to add constraints to.)

#[ExtendsValidationFor(TargetClass::class)]abstractclass SourceClass{    #[Assert\NotBlank(groups: ['my_app'])]    #[Assert\Length(min:3, groups: ['my_app'])]publicstring$name ='';    #[Assert\Email(groups: ['my_app'])]publicstring$email ='';    #[Assert\Range(min:18, groups: ['my_app'])]publicint$age =0;}

(I made the class abstract because it's not supposed to be instantiated - but it's not mandatory.)

Here are the basics of how this works:

  1. During container compilation, classes marked with#[ExtendsValidationFor(Target::class)] are collected and validated: the container checks that members declared on the source exist on the target. If not, aMappingException is thrown.
  2. The validator is configured to map the target to its source classes.
  3. At runtime, when loading validation metadata for the target, attributes (constraints, callbacks, group providers) are read from both the target and its mapped source classes and applied accordingly.

@alexandre-daubois
Copy link
Member

The feature seems nice, but I'm still trying to grasp what it really does. If I understand correctly and if we take Sylius example, is the following code correct?

useSylius\Component\Product\Model\ProductTranslation;#[ValidationFor(ProductTranslation::class)]class MyProductTranslation{    #[Assert\NotBlank(groups: ['my_app'])]     #[Assert\Length(min:10, groups: ['my_app'])]publicstring$name ='';}

Then on validation, Sylius'ProductTranslation constraints would be overridden by the ones defined inMyProductTranslation. Is that right?

@nicolas-grekas
Copy link
MemberAuthor

@alexandre-daubois you've got it right, provided you also configure thesylius.form.type.product_translation.validation_groups parameter as explained in the doc.
That's already doable using yaml and xml but not using plain PHP attributes.

@OskarStarkOskarStark changed the title[Validator] Add #[ValidationFor] to declare new constraints for a class[Validator] Add#[ValidationFor] to declare new constraints for a classAug 29, 2025
@OskarStark
Copy link
Contributor

Could we find a proper tribute name with something like#[As*]?

@nicolas-grekas
Copy link
MemberAuthor

@OskarStark that's not a service.As* is for services to me.

OskarStark reacted with thumbs up emoji

Copy link
Member

@alexandre-dauboisalexandre-daubois left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Does this work with class constraints? I don't think I saw support or tests for them. I wonder if they should be supported for feature completeness?

@nicolas-grekas
Copy link
MemberAuthor

Thank you@alexandre-daubois and@stof, I addressed your comments.

@nicolas-grekasnicolas-grekas changed the title[Validator] Add#[ValidationFor] to declare new constraints for a class[Validator] Add#[ExtendsValidationFor] to declare new constraints for a classAug 30, 2025
Copy link
Member

@alexandre-dauboisalexandre-daubois left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The feature is a bit puzzling to me (having a class that “lives” somewhat on its own and is never actually used in the code except by the container), but the use case is relevant so looks fine 👍

kaznovac reacted with thumbs up emoji
fabpot added a commit that referenced this pull requestSep 2, 2025
…ct classes for resource definitions (nicolas-grekas)This PR was merged into the 7.4 branch.Discussion----------[DependencyInjection] Parse attributes found on abstract classes for resource definitions| Q             | A| ------------- | ---| Branch?       | 7.4| Bug fix?      | no| New feature?  | yes| Deprecations? | no| Issues        | -| License       | MITThis PR improves support for resource definitions by allowing to parse attributes on abstract classes.This can be useful for PRs like#61563 and#61545, so that the attribute proposed there could be set on abstract classes.Commits-------6571f7b [DependencyInjection] Parse attributes found on abstract classes for resource definitions
@alexander-schranz
Copy link
Contributor

alexander-schranz commentedSep 5, 2025
edited
Loading

We have the same issue when removing XML and Yaml for Validation we require a way that a Project can add new validations to third party classes of@sulu.

We are fine with whatever alternative Symfony provides our CMS users, personally I would maybe go more with something like:

class CustomUserValidationProvider{    #[UserValidationProviderFor(User::class)]publicstaticfunctionloadValidatorMetadata(ClassMetadata$metadata):void    {$metadata->addPropertyConstraint('name',newNotBlank());    }}

Very similar how you could already haveloadValidatorMetadata on the Entity itselfsee PHP way here. But we could add both kind of ways.

valtzu and kaznovac reacted with thumbs up emoji

@stof
Copy link
Member

stof commentedSep 5, 2025

@alexander-schranz that would be a separate feature, which can totally be added in parallel if projects prefer using the PHP metadata API than adding attributes.

nicolas-grekas and alexander-schranz reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

@alexander-schranz thanks for chiming in and for the proposal.
On my side, I prefer the attribute-way because it doesn't require learning about the ClassMetadata API, which is totally different than attributes.
I get that config classes like this might be unusual, but they're nonetheless a very good substrate for configuration via attributes. I ensured such classes could be made abstract, to prevent using them for anything else.

alexander-schranz reacted with thumbs up emoji

@fabpot
Copy link
Member

Thank you@nicolas-grekas.

@fabpotfabpot merged commitf603472 intosymfony:7.4Sep 10, 2025
10 of 12 checks passed
fabpot added a commit that referenced this pull requestSep 10, 2025
…re new serialization attributes for a class (nicolas-grekas)This PR was merged into the 7.4 branch.Discussion----------[Serializer] Add `#[ExtendsSerializationFor]` to declare new serialization attributes for a class| Q             | A| ------------- | ---| Branch?       | 7.4| Bug fix?      | no| New feature?  | yes| Deprecations? | no| Issues        | -| License       | MITThis PR builds on#61532It's a sibling of#61545I propose to add a `#[ExtendsSerializationFor]` attribute that allows adding serialization attributes to another class.This is typically needed for third party classes. For context, Sylius has a nice doc about this:https://docs.sylius.com/the-customization-guide/customizing-serialization-of-apiAt the moment, the only way to achieve this is by declaring the new attributes in the (hardcoded) `config/serialization/` folder, using either xml or yaml. No attributes.With this PR, one will be able to define those extra serialization attributes using PHP attributes, set on classes that'd mirror the properties/getters of the targeted class. The compiler pass will ensure that all properties/getters declared in these source classes also exist in the target class. (source = the app's class that declares the new serialization attributes; target = the existing class to add serialization attributes to.)```php#[ExtendsSerializationFor(TargetClass::class)]abstract class SourceClass{    #[Groups(['my_app'])]    #[SerializedName('fullName')]    public string $name = '';    #[Groups(['my_app'])]    public string $email = '';    #[Groups(['my_app'])]    #[MaxDepth(2)]    public Category $category;}```(I made the class abstract because it's not supposed to be instantiated - but it's not mandatory.)Here are the basics of how this works:1. During container compilation, classes marked with `#[ExtendsSerializationFor(Target::class)]` are collected and validated: the container checks that members declared on the source exist on the target. If not, a `MappingException` is thrown.2. The serializer is configured to map the target to its source classes.3. At runtime, when loading serialization metadata for the target, attributes (groups, serialized names, max depth, etc.) are read from both the target and its mapped source classes and applied accordingly.Commits-------386f949 [Serializer] Add `#[ExtendsSerializationFor]` to declare new serialization attributes for a class
@nicolas-grekasnicolas-grekas deleted the validator.for branchSeptember 10, 2025 12:12
This was referencedOct 27, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@stofstofstof left review comments

@fabpotfabpotfabpot approved these changes

@alexandre-dauboisalexandre-dauboisalexandre-daubois approved these changes

@xabbuhxabbuhAwaiting requested review from xabbuh

@ycerutoycerutoAwaiting requested review from yceruto

+1 more reviewer

@ro0NLro0NLro0NL left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

7.4

Development

Successfully merging this pull request may close these issues.

8 participants

@nicolas-grekas@alexandre-daubois@OskarStark@alexander-schranz@stof@fabpot@ro0NL@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp