Skip to content

[Validator] Add option to override property constraints in child class #36155

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

przemyslaw-bogusz
Copy link
Contributor

@przemyslaw-bogusz przemyslaw-bogusz commented Mar 21, 2020

Q A
Branch? master
Bug fix? yes
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #15950
License MIT
Doc PR TODO

Currently, property constraints defined in a child class are merged with property constraints of parent class. I believe it's sometimes necessary to override them instead. This PR allows this option to be configurable.

Example

class ParentClass
{
    /**
     * @Assert\GreaterThanOrEqual(1)
     */
    public $example = 1;
}

class ChildClass extends ParentClass
{
    /**
     * @Assert\GreaterThanOrEqual(0)
     * @Assert\EnableOverridingPropertyConstraints()
     */
    public $example = 0;
}

@xabbuh
Copy link
Member

xabbuh commented Mar 21, 2020

This would solve #15950, right?

@xabbuh xabbuh added this to the next milestone Mar 21, 2020
@przemyslaw-bogusz
Copy link
Contributor Author

This would solve #15950, right?

Yes, it allows you to achieve the effect described there. In fact, I began my PR by looking at your solution from #21053.

@blowski
Copy link

blowski commented Mar 28, 2020

I'll start by saying I'm not a fan of inheritance, because it so often causes these kinds of issues, so I'd usually look for a way of solving this in a different way. That said, I appreciate some codebases might not be able to avoid it.

So my opinions:

  1. I feel a bit uncomfortable with it being an "assertion" when it's not itself asserting anything, but only changing other assertions.
  2. Can you override or disable assertions on private properties? I don't know how this behaves at present, so perhaps it's a non-issue.

@przemyslaw-bogusz
Copy link
Contributor Author

przemyslaw-bogusz commented Mar 29, 2020

I feel a bit uncomfortable with it being an "assertion" when it's not itself asserting anything, but only changing other assertions.

There are a few of that type already, e.g. AtLeastOneOf, EnableAutoMapping.

Can you override or disable assertions on private properties? I don't know how this behaves at present, so perhaps it's a non-issue.

Yes. Currently - apart from my PR - constraints are merged even for private properties.

@blowski
Copy link

blowski commented Mar 30, 2020

Good point that this is already a pattern used elsewhere. EnableAutoMapping definitely feels like configuration and not a constraint.

For me personally, it would help if I could understand how properties and constraints behave with inheritance. Could I help with that, or have you already got something you could share?

@przemyslaw-bogusz
Copy link
Contributor Author

For me personally, it would help if I could understand how properties and constraints behave with inheritance. Could I help with that, or have you already got something you could share?

The validation process creates metadata classes, that contain information like constraints against which an object and its properties should be validated, TraversalStrategy, etc. PropertyMetadata, which contains metadata regarding object's property, uses ReflectionProperty to get value of the validated property. The refelection's property accessibility is set to true, which allows it to access protected and private properties of the validated object.

@nicolas-grekas
Copy link
Member

@przemyslaw-bogusz can you please update the description and link to the fixed issue? Note that we recommend keeping all rows in the template table.

@przemyslaw-bogusz przemyslaw-bogusz force-pushed the override_property_constraints branch from 4521d60 to 3a230f2 Compare April 4, 2020 07:11
@xabbuh
Copy link
Member

xabbuh commented Apr 9, 2020

What about making this an option in the base Constraint class instead? That would also allow for making this decision per constraint.

@fabpot
Copy link
Member

fabpot commented Aug 17, 2020

@przemyslaw-bogusz Do you have time to take feedback into account?

@fabpot
Copy link
Member

fabpot commented Sep 19, 2020

@przemyslaw-bogusz Do you think you will have time to finish this PR in the next few weeks?

@przemyslaw-bogusz
Copy link
Contributor Author

I've been thinking about @xabbuh 's suggestion and I can see one problem with this approach.

In the current proposal, if you choose to override constraints, you can either give the child class same set of constraints but with different options or a completely different set of constraints. For example, if the parent class has Length(max="5"), the child class can override it and can have one of the following scenarios (or any other):

  1. Length(max="10")
  2. NotBlank()
  3. no constraints at all

If we make this an option in the Constraint class, the child class will only be able to override given constraint with a constraint of the same kind but with different options (point 1 of the above example) and it will not be able to achieve scenarios described in point 2 and 3 - it will not be able to discard constraints of the parent class.

Please correct me if I'm wrong. Nevertheless, I will gladly amend the PR, if it's the only way for it to be approved.

@fabpot fabpot closed this Oct 7, 2020
@fabpot
Copy link
Member

fabpot commented Oct 7, 2020

We've just moved away from master as the main branch to use 5.x instead. Unfortunately, I cannot reopen the PR and change the target branch to 5.x. Can you open a new PR referencing this one to not loose the discussion? Thank you for your understanding and for your help.

@nicolas-grekas nicolas-grekas modified the milestones: 5.x, 5.2 Oct 14, 2020
@connorhu
Copy link
Contributor

connorhu commented Oct 15, 2020

What can I do to this PR to merge/finish?

@TerjeBr
Copy link

TerjeBr commented Mar 12, 2024

Can we please have this PR merged?
I just now needed in my code to override asserts in a child class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants