Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony validator inheritance

I have two entity classes:

class A {

/**
 * @Assert\LessThanOrEqual(3)
 *
 * @var int
 */
protected $attempts;

}

class B extends A {

/**
 * @Assert\LessThanOrEqual(5)
 *
 * @var int
 */
protected $attempts;

}

And 1 test to check that validation works correctly:

public function testSetAttemptsCount()
{
    $block = new B();
    $block->setAttempts(6);

    $errors = $this->getService('validator')->validate($block);
    $this->assertHasViolation($errors, 'attempts', LessThanOrEqual::TOO_HIGH_ERROR);

    $block->setAttempts(4);
    $errors = $this->getService('validator')->validate($block);
    $this->assertNotHasViolation($errors, 'attempts', LessThanOrEqual::TOO_HIGH_ERROR);
}

This test will not pass because it validates assert value from class A. Does anybody know how can I "rewrite" validation rule for field?

like image 612
alvery Avatar asked Jul 30 '18 16:07

alvery


Video Answer


1 Answers

I am going to conclude my search for the solution for now. It is clear that there was an attempt to resolve this but it caused some sort of BC breakage, however I have not found any mentions of it (so we could better understand it). After all, major versions allow BC breaks and, in my opinion, either 3.0 or 4.0 were a good candidates for this, but somehow slipped thought.

The best lead I've got (but not sufficient nor ideal in any means) is the quote from docs:

This means you are able to add new constraints to a property, but you cannot override them ... To create your own validation, add the constraints to a new validation group

Indeed, defining own own validation groups could be a potential solution to this, but we are back to square one if we do not have a control over parent classes (and we usually don't). So, this would involve redefining all of the properties from base class in our child class. This really beats the purpose.

Derived on above, somewhat less funky solution can be applied, if we externalize our validation rules to YAML or XML. So, no annotations. In YAML, that would look something like this:

App\Data\Foo:
    properties:
        attempts:
            - LessThanOrEqual: 2
        another:
            - LessThanOrEqual: 5

App\Data\Bar:
    properties:
        attempts:
            - LessThanOrEqual: {value: 5, groups: [Overriden]}
        another:
            - LessThanOrEqual: {value: 5, groups: [Overriden]}

In the config example above, Bar extends Foo and we can copy and paste existing validation rules and stick the custom group (Overriden in my case) and use it. That way, we validate those constraints coming from parent class, that are of interest to us and include our own from child class. Slightly more effort is needed if parent class uses different validation rule format...

I am eager to see if anyone can come up with better aproach as I feel this should really work our-of-box...

Hope this helps a bit...

like image 89
Jovan Perovic Avatar answered Nov 10 '22 00:11

Jovan Perovic