Home > Software engineering >  Cause Symfony validation constraint annotations to cascade
Cause Symfony validation constraint annotations to cascade

Time:09-23

I have a class called NamedAdapter that has some properties. These properties are being fed by a Symfony form, and they have some validation constraints listed above them as annotations. When the properties that reside directly within the NamedAdapter class are not what is desired, they rightly cause one or more ConstraintViolation complaints to appear during form validation.

The problem is that NamedAdapter and its related form type also contain references to compound fields that are their own form types, and that have other, smaller classes associated with them. For simplicity, we'll call those classes SmallerClassOne and SmallerClassTwo.

These other, smaller classes also have annotations that specify validation desires, but when those annotations are disobeyed, no complaint shows up.

I have tried setting error_bubbling to true but, as I expected, this did not cause a change in behavior. (If I understand that option correctly, it has more to do with how errors are displayed, rather than whether they're displayed.)

Is there some sort of class-wide annotation that I should be applying to the class definitions of the smaller component classes (SmallerClassOne and SmallerClassTwo) in order to get their validation problems to show up during form validation? If so, what is it?

EDITS:

-- The form types are nested within one another.

-- The @Assert\Valid() annotation is already present above the fields that contain SmallerClassOne and SmallerClassTwo in the top-level class.

-- Here is a slightly modified copy of the code that's being used. Submitting the string "bob" as the latitude does not induce a ConstraintViolation.

<?php

class NamedAdapter implements SomeInterface
{
    /** @Assert\Valid */
    private ?SmallerClassOne $mySmallerObject = null;


    /** @Assert\Valid */
    private ?SmallerClassTwo $myOtherSmallerObject = null;

    ...

}

class SmallerClassOne
{
     /**
     * @Assert\Type(type="float", message="The value {{ value }} is not a valid {{ type }}.")
     */
    private ?float $latitude;

    ....
}

class SmallerClassTwo
{
     /**
     * @Assert\Type(type="float", message="The value {{ value }} is not a valid {{ type }}.")
     */
    private ?float $latitude;

    ....
}

CodePudding user response:

The problem was that the $latitude and $longitude fields were not being set directly via setters for those fields, but through a compound setCoordinates() method. So I had to use @ORM\HasLifecycleCallbacks at the tops of SmallerClassOne and SmallerClassTwo, then create something like the following farther down:

/** @Assert\Callback(methods={"setCoordinates"}) */
public function assertValidLatitude(ExecutionContextInterface $context): void
{
    if (!is_float($this->latitude)) {
        $context
            ->buildViolation('latitude must be a float')
            ->atPath('my.property.path')
            ->addViolation();
    }
}

That seems to have done the trick.

EDIT: This did not actually work, which makes sense, as the property I was validating had not been populated yet. I will leave this answer up, though, in case it leads someone to a useful piece of information.

CodePudding user response:

In the Twig you can display errors like this:

{% if not form.vars.valid %}
    <ul>
    {% for error in form.vars.errors %}
        <li >{{error.message}}</li>
    {% endfor %}
    </ul>  
{% endif %}
  • Related