2

I'm trying to pass a extra option to my form type in Symfony 2.6.1 as follow (FabricanteForm.php):

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
            ->add('nombre', 'text')
            ->add('direccion', 'textarea')
            ->add('telefono', 'text', array(
                'required' => TRUE,
                'trim' => TRUE,
            ))
            ->add('fax', 'text', array(
                'required' => FALSE,
            ))
            ->add('correo', 'email', array(
                'required' => FALSE,
            ));

    if ($options['isFabricante'] !== null)
    {
        $builder->add('pais', 'text');
    }
    else
    {
        $builder->add('pais', 'entity', array(
            'class' => 'AppBundle:Pais',
            'property' => 'nombre',
            'query_builder' => function (EntityRepository $er) {
                return $er->createQueryBuilder('qb')
                          ->where('qb.activo = :activoValue')
                          ->setParameter('activoValue', true);
            },
            'mapped' => FALSE,
            'expanded' => FALSE,
            'multiple' => TRUE,
        ));
    }
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setOptional(array(
        'isFabricante',
    ));

    $resolver->setDefaults(array(
        'data_class' => 'Sencamer\AppBundle\Entity\FabricanteDistribuidor',
        'intention' => 'fabricante',
        'isFabricante' => null
    ));
}

And then I create the form on controller as follow:

$entityPais = new Entity\Pais();
$formPaisesDistribuidor = $this->createForm(new Form\PaisesForm(), $entityPais, array('isFabricante' => null));
$formPaisesFabricante = $this->createForm(new Form\PaisesForm(), $entityPais, array('isFabricante' => true));

But I got this error:

The option "isFabricante" does not exist. Known options are: "action", "allow_extra_fields", "attr", "auto_initialize", "block_name", "by_reference", "cascade_validation", "compound", "constraints", "csrf_field_name", "csrf_message", "csrf_protection", "csrf_provider", "csrf_token_id", "csrf_token_manager", "data", "data_class", "disabled", "empty_data", "error_bubbling", "error_mapping", "extra_fields_message", "inherit_data", "intention", "invalid_message", "invalid_message_parameters", "label", "label_attr", "label_format", "mapped", "max_length", "method", "pattern", "post_max_size_message", "property_path", "read_only", "required", "translation_domain", "trim", "validation_groups", "virtual".

Is that the right way to set extra parameters on a Form Type? Is this the best way to reuse the form? (As you may notice the only difference between $formPaisesDistribuidor and $formPaisesFabricante is pais field type, first one is a entity and second one is just a text)

Any help? Advice?

5
  • As you discovered, each form type has a specific list of options. It's easiest to just pass your parameter as a constructor argument. Commented Dec 30, 2014 at 23:32
  • @Cerad the weird part, unless that's changed on 2.6.x, is that I use the same approach in 2.5.x project. Anyway I just give a try to your suggestion, thx Commented Dec 30, 2014 at 23:42
  • Interesting about 2.5. I ran into this back in the days of 2.0 or 2.1. Commented Dec 31, 2014 at 2:29
  • Your approach should still work in 2.6, I just tested it on a form of mine using your method. Commented Dec 31, 2014 at 5:15
  • 1
    @ReynierPM you should move this condition to symfony.com/doc/current/cookbook/form/… Commented Dec 31, 2014 at 11:33

2 Answers 2

2

Referencing Turdaliev's point about $options not being used for what he wants - I disagree, you can definitely use it for that. Symfony's documentation shows both ways.

Here is a Symfony example passing in the entity manager to the options array:

http://symfony.com/doc/current/cookbook/form/data_transformers.html#using-the-transformer

Here is another Symfony example passing in choices to the constructor:

http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html#creating-your-field-type-as-a-service

Looking at the Symfony Forms Best Practices, they do not tell you which method is preferred, so you can decide for yourself.

I like to use the $options array for simple boolean flags...since they are options. Plus if you have several fields with some that are optional and some that are required, you don't have to mess around with constructor parameter ordering.

As for why you are receiving the error, I'm not entirely sure. In Symfony 2.6, setOptional() is now setDefined(). You can still use the old function but it is deprecated and will be removed in 3.0. Also, you no longer have to pass an array if you're passing just one option. You also don't have to set it in setDefaultOptions()

Try this:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefined('isFabricante');

    $resolver->setDefaults(array(
        'data_class' => 'Sencamer\AppBundle\Entity\FabricanteDistribuidor',
        'intention'  => 'fabricante',
    ));
}
Sign up to request clarification or add additional context in comments.

2 Comments

I was looking in UPGRADE file from 2.5.x to 2.6.x and I notice that also has changed OptionsResolverInterface to OptionsResolver so my doubt regarding this is in the past I declare use ...\OptionsResolverInterface now I should declare use ...\OptionsResolver, which is the right way?
I just looked at Symfony's AbstractType and it still uses OptionsResolverInterface, so it looks like for Forms you'd still keep it as the interface rather than OptionsResolver
1

As you can see from exception, $options parameter is not used for what you are using for. So instead of passing your custom options to Symfony's standard $options parameter, you could create custom constructor function for FabricanteForm class. Following is a demonstration of how all these things could be done:

PraisesType

namespace School\CoreBundle\Form\Type;


use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class PraisesType extends AbstractType
{

private $options;

public function __construct($options)
{
    $this->options = $options;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
        $builder
            ->add('nombre', 'text')
            ->add('direccion', 'textarea')
            ->add('telefono', 'text', array(
            'required' => TRUE,
                'trim' => TRUE,
            ))
            ->add('fax', 'text', array(
                'required' => FALSE,
            ))
            ->add('correo', 'email', array(
                'required' => FALSE,
            ));

        if ($this->options['isFabricante'] !== null)
        {
            $builder->add('pais', 'text');
        }
        else
        {
            $builder->add('pais', 'entity', array(
                'class' => 'AppBundle:Pais',
                'property' => 'nombre',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('qb')
                        ->where('qb.activo = :activoValue')
                        ->setParameter('activoValue', true);
                },
                'mapped' => FALSE,
                'expanded' => FALSE,
                'multiple' => TRUE,
            ));
        }
    }


    public function getName()
    {
        return 'praises';
    }
}

Usage

    $entityPais = new Entity\Pais();
    $formPaisesDistribuidor = $this->createForm(new Form\PaisesType(array('isFabricante' => null)), $entityPais);
    $formPaisesFabricante = $this->createForm(new Form\PaisesType(array('isFabricante' => true)), $entityPais);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.