Jordi Puig
Jordi Puig

Reputation: 224

Define form as service in symfony 3.0

I know there are 2 other questions about it, but I think none of them solves what I will ask.

In Symfony 2.8 there is a deprecation note about tagging a form defined as a service with an "alias", thant can be used to pass to "createForm" to get the form.

So please correct me if I'm wrong, now we have to define the service without the alias tag:

#src/MyBundle/Resources/config/services.yml
my.form.as.service:
    class: MyBundle\Form\Type\MyFormType
    arguments: ["@doctrine.orm.entity_manager",%myparameter1%]
    tags: { - name: form.type }

And in the controller:

$form = $this->createForm('my.form.as.service');

But this gives me a form naming error, as the form returns 'my_name' in getName function, and it expects the form to receive FQCN. OK, following other responses here in controller I changed to:

use MyBundle\Form\Type\MyFormType;
...
$form = $this->createForm(MyFormType::class)

That works, and in github symfony members says that form component does all the work... but what if I want to define a seccond service with the same class but with another parameter instead of %parameter1%. In 2.8 and older I was able to do that defining another service and passing its name to createForm function, but now that it gets the class directly, can I do that? (I know that do it can be strange or unnecessary or...).

And to symfony members: I'm with Javiereguiluz that this change makes you write more code and makes you not have the full control of how the form component uses your service. Was so necessary removing form alias to make our live so complicated? Thanks!

Upvotes: 3

Views: 624

Answers (2)

Wouter J
Wouter J

Reputation: 41934

Sorry, I misread your question at first. Now, the correct answer:

If your form type needs to have a dynamic configuration setting (e.g. a parameter), a form type option should be created instead. This allows to dynamically change this setting:

class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $form, array $options)
    {
        $options['your_setting']; // read the option
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setRequired('your_setting'); // add a required option
    }
}

Usage:

$this->createForm(MyFormType::class, null, [
    'your_setting' => 'some value',
]);

Alternatively, you can also default the setting to some static value or to a parameter:

class MyFormType extends AbstractType
{
    private $yourSetting;

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

    // ...

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('your_setting', $this->yourSetting);
    }
}

You can read more about this in the OptionsResolver component documentation.

Upvotes: 3

Michaël Perrin
Michaël Perrin

Reputation: 6238

I asked the same question and answered myself here: Symfony 2.8/3.0 upgrade: how to deal with form types with variable parameters?

Unfortunately this is a limitation in Symfony 3.0 and there is no solution for it.

One solution is to create one class for each form (instead of a common one) and make each of them extend a common abstract class to avoid code duplication.

But that still required you to create many classes, which is not optimal.

Upvotes: 0

Related Questions