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

Appearance settings

[Validator] Valid() with groups should not replace validation groups #32900

Copy link
Copy link
Open
@iquito

Description

@iquito
Issue body actions

Symfony version(s) affected: 3.4+

Description

In Symfony 3.4 validation groups were added to the Valid() constraint as an option. Yet validation groups for Valid() behave completely different than with any other assertion: usually validation groups define if an assertion should trigger or not. With Valid() it also redefines the validation group for the object and replaces the validation group (which is also not in the documentation) leading to reduced usability and a high chance of things working completely different than anticipated.

How to reproduce

use Symfony\Component\Validator\Constraints as Assert;

class Address
{
    /**
     * @Assert\NotNull()
     * @Assert\NotBlank()
     */
    public $street;

    /**
     * @Assert\NotNull(groups={"cityAddress"})
     */
    public $city;
}

class Order
{
    /**
     * @Assert\NotNull
     */
    public $firstName = '';

    /**
     * @Assert\Valid()
     */
    public $address;

    /**
     * @Assert\Valid(groups={"alternateInvoiceAddress"})
     */
    public $invoiceAddress;
}

$order = new Order();
$order->address = new Address();
$order->invoiceAddress = new Address();

// Leads to two violations: address.street should not be null
// and address.street should not be blank - so far so good
$violations = $validator->validate($order);

// Leads to the same two violations, as "alternateInvoiceAddress"
// triggers validation for $invoiceAddress, but only for the
// "alternateInvoiceAddress" validation group within that object,
// and "cityAddress" is never propagated to the $invoiceAddress object
$violations = $validator->validate($order, null, ['Default', 'alternateInvoiceAddress', 'cityAddress']);

(I can give a fully working PHP example file if necessary, the above is the most relevant part of it)

Possible Solution

A defined validation group on an assertion should only define when that specific assertion is triggered - in the case of Valid() the assertion means "validate the object". The current double meaning for Valid() is "only trigger when this validation group is set AND only validate this validation group in the subclass" which limits the usefulness severely (GroupSequence cannot be used in the subclass, reusable subclasses are very hard to do) and the behavior is very unintuitive.

Defining which validation groups should be checked in a subclass could be a separate feature, then it would be useful, and by default all validation groups from the parent should be passed to the child - this already happens when no validation group is specified for Valid().

I also think this is a limitation which will come up often in real world examples, like in the example above (which is very near my actual use case): specifying a shipping address and an alternate but optional invoice address, which is only validated if a checkbox is selected - already this simple example is impossible to solve as it stands now. At the same time I cannot see many real world applications for the current behavior.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.