Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Validator] Allow using attributes to declare compile-time constraint metadata#61528
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
[Validator] Allow using attributes to declare compile-time constraint metadata#61528
Uh oh!
There was an error while loading.Please reload this page.
Conversation
289783f to8be45c5Comparedefd051 toea317e8Compared3490c8 to9d08608Comparesrc/Symfony/Component/Validator/DependencyInjection/AttributeMetadataPass.phpShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
3dc6ebf to35c205eComparesrc/Symfony/Component/Form/Extension/Validator/Constraints/Form.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/Validator/DependencyInjection/AttributeMetadataPass.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
src/Symfony/Component/Validator/DependencyInjection/AttributeMetadataPass.phpShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
325c0c3 tocd349b8Comparesrc/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.phpShow 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.
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.
ca89d23 todbe819bComparedbe819b to0197b50CompareThere 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
c539c77 intosymfony:7.4Uh oh!
There was an error while loading.Please reload this page.
…-time serialization metadata (nicolas-grekas)This PR was merged into the 7.4 branch.Discussion----------[Serializer] Allow using attributes to declare compile-time serialization metadata| Q | A| ------------- | ---| Branch? | 7.4| Bug fix? | no| New feature? | yes| Deprecations? | yes| Issues | -| License | MITVery close to#61528Prerequisite for#61287At the moment, serialization attributes are read at runtime when `framework.serialization.enable_attributes` is true.This means they don't fit for bundles nor can't they be warmed up.This PR fixes both issues by using a new `serializer.attribute_metadata` resource tag, that's turned into a list of classes to parse for attributes at compile-time.For bundles and for apps, the tag is added by explicit service configuration:```php ->set('my_bundle.api_resource.product', Product::class) ->resourceTag('serializer.attribute_metadata')```Unlike validation where we have constraint attributes to auto-discover service resources, serialization doesn't have any corresponding hooks. We do have a few like `#[DiscriminatorMap]` of `#[Groups]`, but relying on those would miss many more classes that are meant for serialization. Maybe we could introduce an attribute that'd hint that some class is serializable by the component (and require the attribute at some point in the future?)Commits-------bc6e054 [Serializer] Allow using attributes to declare compile-time serialization metadata
…ew constraints for a class (nicolas-grekas)This PR was merged into the 7.4 branch.Discussion----------[Validator] Add `#[ExtendsValidationFor]` to declare new constraints for a class| Q | A| ------------- | ---| Branch? | 7.4| Bug fix? | no| New feature? | yes| Deprecations? | no| Issues | -| License | MITThis PR builds on#61528I 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-validationAt 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.)```php#[ExtendsValidationFor(TargetClass::class)]abstract class SourceClass{ #[Assert\NotBlank(groups: ['my_app'])] #[Assert\Length(min: 3, groups: ['my_app'])] public string $name = ''; #[Assert\Email(groups: ['my_app'])] public string $email = ''; #[Assert\Range(min: 18, groups: ['my_app'])] public int $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, a `MappingException` 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.Commits-------e884a76 [Validator] Add `#[ExtendsValidationFor]` to declare new constraints for a class
Uh oh!
There was an error while loading.Please reload this page.
Prerequisite for#61288
At the moment, validation attributes are read at runtime when
framework.validation.enable_attributesis true.This means they don't fit for bundles nor can't they be warmed up.
This PR fixes both issues by using a new
validator.attribute_metadataresource tag, that's turned into a list of classes to parse for attributes at compile-time.For apps, the tag is added by autoconfiguration: any
Constraint-derived attributes found on a class in thesrc/folder will trigger the rule to add the tag.For bundles (and for apps if they want to), the tag is added by explicit service configuration. In an "eat your own dog-food" spirit, this capability is used to declare the constraints of the
Formclass: instead of loading thevalidation.xmlfile, we now declare this service resource:This reads the attributes added to the
Formclass:Bundles can do the same and replace their XML files by attributes.
As a next step, we could also deprecate runtime-discovery of attributes. This could be worth it if this discovery has a measurable performance impact. To be measured if one wants to dig this idea.
Side note: I'm hoping this could allow removing the yaml and xml config formats one day. For serialization metadata also (PR coming). BUT, this doesn't (yet) cover the use case of overriding metadata defined by bundles. For that, apps still have to use xml or yaml in config/validation/. I have an idea to cover this, coming to a next PR if it works.
(failures unrelated)