skip to Main Content

I have this entity class in Symfony/5.4:

use DoctrineORMMapping as ORM;
use SymfonyComponentValidatorConstraints as Assert;

class Assignments
{
    public const SALARY_RANGES = [
        'Red',
        'Green',
        null,
    ];

    /**
     * @ORMColumn(length=255, nullable=true)
     * @AssertChoice(choices=Assignments::SALARY_RANGES, strict=true)
     */
    private ?string $salaryRange;

    /**
     * @ORMManyToOne(targetEntity="Employee", inversedBy="assignments")
     * @ORMJoinColumn(name="employee_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private ?Employee $employee;
}

I need to ensure that salaryRange has a non-null value if, and only if, employee is not null. Is it possible to enforce that with constraint annotations?

I’ve been playing with @AssertCallback but I couldn’t figure out how to get the value of the other field. Perhaps it’s not even the right tool.

/**
 * @AssertCallback({"ExampleValidator", "assertEmployeeOnlyCallback"})
 */
public static function assertEmployeeOnlyCallback(mixed $data, ExecutionContextInterface $context): void
{
    // `$data` contains value from `salaryRange` but, where is `employee`?
}

2

Answers


  1. Chosen as BEST ANSWER

    You can use an Expression constraint. If the expression is true, validation will pass. If the expression is false, there will be a violation.

    It can be written in a single assertion, but you can write a couple of them in order to provide more accurate messages:

    /**
     * @ORMColumn(length=255, nullable=true)
     * @AssertExpression(
     *     "value !== null || this.getEmployee() === null",
     *     message="This value should not be null for employee assignments."
     * )
     * @AssertExpression(
     *     "value === null || this.getEmployee() !== null",
     *     message="This field can only be set for employee assignments."
     * )
     * @AssertChoice(choices=Assignments::SALARY_RANGES, strict=true)
     */
    private ?string $salaryRange = null;
    

    In my case, I also had to set a default value because I'm using a PHP typed property.


  2. just follow the documentation

    https://symfony.com/doc/5.3/reference/constraints/Callback.html

    class Author
    {
        // ...
        private int $field = 1;
        private string $otherField;
       /**
        * @AssertCallback
        */    
        public function validate(ExecutionContextInterface $context, mixed $payload): void
        {
            
            if ($this->field > 1 && $this->otherField != '') {
                $context->buildViolation('Your validation message')
                    ->atPath('toherField')
                    ->addViolation();
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search