Search code examples
phpsymfonysymfony-formssymfony-2.8symfony-validator

Passing constraints to symfony collection type


Symfony 2.8. I'm using a collection with custom entry as a form, with some constraints passed to it. Now my code looks like:

FirstFormType.php:

class FirstFormType extends AbstractFormType
{
    /** @inheritdoc */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('rates', CollectionType::class, [
                'entry_type'   => new SecondFormType([new LessThanOrEqual(300)]),
                'allow_add'    => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'constraints'  => [
                    new NotBlank(),
                    new Count(['min' => 1]),
                ],
            ])
        ;
    }
}

SecondFormType.php:

class SecondFormType extends AbstractFormType
{
    /** @var array */
    private $constraints;

    /** @param array $constraints */
    public function __construct(array $constraints = [])
    {
        $this->constraints = $constraints;
    }

    /** @inheritdoc */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('amount', NumberType::class, [
                'scale'       => 2,
                'constraints' => array_merge($this->constraints, [new CustomConstraint()]),
            ])
        ;
    }
}

Also I had the ThirdFormType, which is the same as FirstFormType but with other constraints passed to SecondFormType. But I want to replace new SecondFormType([...]) to FQCN, and I think I can inherit constraints more correctly. Do you have any ideas how can I do such?


Solution

  • The recommended way to migrate this kind of constructor arguments from form types is creating form options for them, something like this:

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('amount_constraints', array());
    }
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('amount', NumberType::class, [
                'scale' => 2,
                'constraints' => array_merge($options['amount_constraints'], [new CustomConstraint()]),
            ])
        ;
    }
    

    Then, the usage of your new option looks like this:

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('rates', CollectionType::class, [
                'entry_type'   => SecondFormType::class,
                'entry_options' => [
                    'amount_constraints' => [new LessThanOrEqual(300)], 
                ],
                // ...
            ])
        ;
    }