Wolfer Wolfer - 7 months ago 46
PHP Question

Symfony: Custom subform validation

I have form witch uses custom non-mapped subform.

public function buildForm(FormBuilderInterface $builder, array $options) {

$builder->add('subtype', 'my-subtype');
}
}


The subform is consisting of multiple fields and I need to perform additional check on both of them together. The Callback constraint is perfect for the job. However I can not find a way how to add this constraint on the subform as a whole.

So far I have tried to set the Callback in setDefaultOptions() or set it with setAttribute() in buildForm() but the callback is not evaluated.

Currently I am just adding the Callback to one of the fields:

public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('field1', 'text')
->add(
'field2', 'text',
array(
'constraints' => array(
new Callback(array(
'methods' => array(array($this, 'validateMyType'))
))
)
));
}

public function validateMyType($data, ExecutionContextInterface $context) {
// Validation failed...
$context->addViolationAt('subtype', "mySubtypeViolation");
return;
}


This however prevents me to add the violation on the whole subtype. What ever I use in addViolationAt() the violation is always added to field which hosts the Callback constraint.

Answer

Firstly I had typo in the configuration so the callback method was not triggered. Secondly the error-bubbling was automatically set so the error was added to the whole form. So only what I needed was to manually disable it.

public function setDefaultOptions(OptionsResolverInterface $resolver) {
    $resolver->setDefaults([
        'error_bubbling' => false, // Automatically set to true for compound forms.
        'constraints' =>
        array(
            new Callback(array(
                'methods' => array(array($this, 'validateMyType'))
                ))
    )]);
}

Than the violation is added like for any other callback:

public function validateFacrMembership($data, ExecutionContextInterface $context) {
    $context->addViolation("facr.notMember");
}
Comments