Question

I've been trying to use the Symfony 2 forms lately, which are quite good for simple forms.

But -for use in select boxes or something similar- I often want a list of associated entities in the form. In several blogposts and Symfony docs, they suggest something like this...

//BlogPostType implements FormTypeInterface
public function buildForm(FormBuilderInterface $builder, array $options)
{
  $builder
  ->add('category', null, array(
    'property' => 'name',
    'query_builder' => function(EntityRepository $er) use($options) {
      return $er->createQueryBuilder('category')->orderBy('category.name', 'ASC');
    }
  );
}

As I am paying a lot of attention to domain-driven-design and especially separation of concerns, I find it hard to believe that the only option to bind associated entities to a custom form type in Symfony, is by querying for it in the custom form type.

In my opinion, this violates SoC, because forms should not be querying. This way, the form always takes the same entities, but it's not the form who should chose which entities are displayed...

The controller, who asks the form builder to build a form, should inject the associated objects into the custom form type constructor or so...

//BlogPostType implements FormTypeInterface
public function __construct(array $categories) {
  $this->categories = $categories;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
  $builder
    ->add('category', null, array(
      'property' => 'name',
      'choices' => $this->categories
    );
}

Does anyone know how this can be achieved?

Was it helpful?

Solution

Yes, you can pass the choices from the controller. Just create an option instead of injecting it via the constructor, because the constructor will be used only when creating the first form of a given type per request. So, if you happen to need to output more than one form of the same type on a page, their choices will be the same if passed via the constructor.

Injecting something to a form type via the constructor makes sense when you inject services that can be reused several times without any problems.

A lot of examples in docs and around the Web violate a lot of best practices, but it would be much harder to teach a newbie something with examples respecting the practices.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top