Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One field should not be blank if some fields are blank in Symfony Form

Tags:

php

symfony

In my Symfony 2 (2.4.2) application, there is a Form Type which consists of 3 fields.

I'd like the validation be like this: If field A and field B are blank, field C should not be blank. This means that at least one field should receive some data.

Currently, I check the received data in the controller. Is there a more recommended way to do this?

like image 213
pikachu0 Avatar asked Feb 19 '14 08:02

pikachu0


2 Answers

There are even easier solutions than writing a custom validator. The easiest of all is probably the expression constraint:

class MyEntity
{
    private $fieldA;

    private $fieldB;

    /**
     * @Assert\Expression(
     *     expression="this.fieldA != '' || this.fieldB != '' || value != ''",
     *     message="Either field A or field B or field C must be set"
     * )
     */
    private $fieldC;
}

You can also add a validation method to your class and annotate it with the Callback constraint:

/**
 * @Assert\Callback
 */
public function validateFields(ExecutionContextInterface $context)
{
    if ('' === $this->fieldA && '' === $this->fieldB && '' === $this->fieldC) {
        $context->addViolation('At least one of the fields must be filled');
    }
}

The method will be executed during the validation of the class.

like image 139
Bernhard Schussek Avatar answered Nov 15 '22 21:11

Bernhard Schussek


This is probably a use case for a Custom Validation Constraint. I haven't used it myself but basically you create a Constraint and a Validator. You then specify your Constraint in your config/validation.yml.

Your\Bundle\Entity\YourEntity:
    constraints:
        - Your\BundleValidator\Constraints\YourConstraint: ~

The actual validation is done by your Validator. You can tell Symfony to pass the whole entity to your validate method to access multiple fields with:

public function getTargets()
{
    return self::CLASS_CONSTRAINT;
}

And your validate:

public function validate($entity, Constraint $constraint)
{
    // Do whatever validation you need
    // You can specify an error message inside your Constraint
    if (/* $entity->getFieldA(), ->getFieldB(), ->getFieldC() ... */) {
        $this->context->addViolationAt(
            'foo',
            $constraint->message,
            array(),
            null
        );
    }
}
like image 38
Syjin Avatar answered Nov 15 '22 19:11

Syjin