Skip to content

[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

Merged
merged 1 commit into from
Jul 12, 2017
Merged

[Validator] Allow to use a property path to get value to compare in comparison constraints #22576

merged 1 commit into from
Jul 12, 2017

Conversation

ogizanagi
Copy link
Contributor

@ogizanagi ogizanagi commented Apr 28, 2017

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:

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.

@ro0NL
Copy link
Contributor

ro0NL commented Apr 28, 2017

propertyPath?

edit; perhaps for sake of the explicitness valuePropertyPath :)

@ogizanagi
Copy link
Contributor Author

@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.

@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Apr 28, 2017
@ogizanagi ogizanagi changed the base branch from master to 3.4 May 17, 2017 18:31
@ogizanagi
Copy link
Contributor Author

ogizanagi commented Jun 25, 2017

Updated to use back propertyPath for the new option name, as it's the common naming we've got in the core for this (original proposition was valuePath). Unless there is a debate about another naming, this should be ready.

@xabbuh
Copy link
Member

xabbuh commented Jun 29, 2017

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'])) {
Copy link
Member

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.

Copy link
Contributor Author

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();
Copy link
Member

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

Copy link
Contributor Author

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

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)?

Copy link
Contributor Author

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

Choose a reason for hiding this comment

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

PropertyAccessor

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops. Good catch.

@ogizanagi
Copy link
Contributor Author

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

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)

Copy link
Contributor Author

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

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@nicolas-grekas
Copy link
Member

Thank you @ogizanagi.

@nicolas-grekas nicolas-grekas merged commit 07c5aa6 into symfony:3.4 Jul 12, 2017
nicolas-grekas added a commit that referenced this pull request Jul 12, 2017
…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
@ogizanagi ogizanagi deleted the feature/validator/comparisons_property_path branch July 12, 2017 12:12
This was referenced Oct 18, 2017
fabpot added a commit that referenced this pull request Jul 8, 2019
…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
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.

6 participants