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?
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.
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
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With