-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Validator] Allow to use a property path to get value to compare in comparison constraints #22576
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
[Validator] Allow to use a property path to get value to compare in comparison constraints #22576
Conversation
edit; perhaps for sake of the explicitness |
@ro0NL: I hesitated. It should be obvious it's the property path to the value to use in comparison, and not anything else. I can't really explain why I had some reservations on this naming. Let's see what people do prefer. |
Updated to use back |
Can you add a new entry to the changelog please? |
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function __construct($options = null) | ||
{ | ||
if (is_array($options) && !isset($options['value'])) { | ||
if (is_array($options) && !isset($options['value']) && !isset($options['propertyPath'])) { |
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.
We should also error if both the value
and the propertyPath
option are given.
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.
Done.
@@ -36,7 +47,16 @@ public function validate($value, Constraint $constraint) | |||
return; | |||
} | |||
|
|||
$comparedValue = $constraint->value; | |||
if ($path = $constraint->propertyPath) { | |||
$object = $this->context->getObject(); |
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.
we need to account for the case where $object
is null
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.
Hmm. Indeed. What should we do in such case? I guess we can only return;
as there is no way to get the value to compare to from null
and should not create a violation (it's the NotNull
constraint role). Right?
private function getPropertyAccessor() | ||
{ | ||
if (null === $this->propertyAccessor) { | ||
if (!class_exists(PropertyAccess::class)) { |
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.
What about failing earlier instead when the constraint definition is evaluated (i.e. in the constructor of AbstractComparison
)?
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.
Done.
@@ -23,6 +27,13 @@ | |||
*/ | |||
abstract class AbstractComparisonValidator extends ConstraintValidator | |||
{ | |||
private $propertyAccessor; | |||
|
|||
public function __construct(PropertyAccess $propertyAccessor = null) |
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.
PropertyAccessor
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.
Oops. Good catch.
Rebased and green. |
} | ||
|
||
if (isset($options['propertyPath']) && !class_exists(PropertyAccess::class)) { | ||
throw new ConstraintDefinitionException(sprintf('The %s constraint requires the Symfony PropertyAccess component to use the "propertyPath" option.', get_class($this))); |
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.
Missing "
around the class name (same above)
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.
No double quotes were used in the existing one. (Fixed though)
@@ -54,6 +54,14 @@ public function provideValidComparisons() | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function provideValidComparisonsToPropertyPath() | |||
{ | |||
yield array(5); |
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.
Why not use return array(5);
. That would be more similar to what we already have and would avoid questions about why the new ones are different.
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.
Done.
…omparison constraints
Thank you @ogizanagi. |
…to compare in comparison constraints (ogizanagi) This PR was merged into the 3.4 branch. Discussion ---------- [Validator] Allow to use a property path to get value to compare in comparison constraints | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | N/A | License | MIT | Doc PR | todo So we can simply declare something like: ```php class Activity { /** * @var \DateTime * * @Assert\DateTime() */ private $startDate; /** * @var \DateTime * * @Assert\DateTime() * @Assert\GreaterThan(propertyPath="startDate") */ private $endDate; // [...] public function getStartDate(): \DateTime { return $this->startDate; } public function getEndDate(): \DateTime { return $this->startDate; } } ``` Of course, this is actually already possible by using an `Expression` constraint (or a callable), but it feels more natural to me to use proper comparison constraints for this. Commits ------- 07c5aa6 [Validator] Allow to use a property path to get value to compare in comparison constraints
…in range constraint (Lctrs) This PR was squashed before being merged into the 4.4 branch (closes #31511). Discussion ---------- [Validator] Allow to use property paths to get limits in range constraint | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | Part of #31503 | License | MIT | Doc PR | symfony/symfony-docs#11793 Similar as #22576, but for the `Range` constraint. Commits ------- 2b50990 [Validator] Allow to use property paths to get limits in range constraint
So we can simply declare something like:
Of course, this is actually already possible by using an
Expression
constraint (or a callable), but it feels more natural to me to use proper comparison constraints for this.