4

I can do $this->createForm(new EntityType(), $entity, array('em' => $em)) from the controller, but how can I pass it to a NestedEntityType()? I guess I can't just pass it on from inside the EntityType->buildForm():

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $entityManager = $options['em'];

    $builder->add('entities', 'collection', array(
        'type' => new NestedEntityType(),
        'allow_add' => true,
        'allow_delete' => true,
        'by_reference' => false
    ));
}

I need the entity manager to setup a data transformer to check if an entity already exists in the database, and use that entity in a relationship instead of creating a new one with the same name.

Resources

Community
  • 1
  • 1
Gergő
  • 588
  • 8
  • 20

3 Answers3

7

You could define your form as a service and then inject Doctrine entity manager in it as an argument.

http://symfony.com/doc/3.4/form/form_dependencies.html

And then declare the service like this:

services:
    acme.type.employee:
        class: Acme\AcmeBundle\Form\Type\FormType
        tags:
            - { name: form.type, alias: form_em }
        arguments: [@doctrine]

And in the form type:

use Doctrine\Bundle\DoctrineBundle\Registry as Doctrine;

/** @var \Doctrine\ORM\EntityManager */
private $em;

/**
 * Constructor
 * 
 * @param Doctrine $doctrine
 */
public function __construct(Doctrine $doctrine)
{
    $this->em = $doctrine->getManager();
}
numediaweb
  • 16,362
  • 12
  • 74
  • 110
Johann
  • 748
  • 5
  • 17
  • **1.** The `FormType` extends `AbstractType`, that doesn't have a constructor, so calling `parent::__construct()` results in a fatal error. **2.** Is there any reason to make the manager available in the object scope, or is it OK to put it into the `buildForm()` function? **3.** What namespace should be used for the `Doctrine` class name? Why not use only the `EntityManager` in the form type like [in this question](http://stackoverflow.com/q/10427282/868052)? – Gergő Mar 16 '14 at 17:19
  • 2
    1. Then just delete this line. 2. I don't think putting it in the `buildForm()` function will work since the arguments of a service are injected in its constructor when it's created. 3. `use Doctrine\Bundle\DoctrineBundle\Registry as Doctrine;` You could inject the entity manager directly like in the other answer, there is no real difference, it's just two of the many different ways to get the entity manager. I'll edit my answer with these corrections. – Johann Mar 16 '14 at 17:50
6

You can use options to pass corresponding data to the subtype:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $entityManager = $options['em'];

    $builder->add('entities', 'collection', array(
        'type' => new NestedEntityType(),
        'allow_add' => true,
        'allow_delete' => true,
        'by_reference' => false
        'options' => array('em' => $entityManager) // <-- THIS
    ));
}

Also, @Johann's solution in the by-the-book one so it's worth spending extra-time doing it as he proposed. My solution is better for passing intermediate controller's data (not services)

Jovan Perovic
  • 19,846
  • 5
  • 44
  • 85
1

Referring to @Johann's answer, if you are working with Symfony version 3 you need to wrap the arguments between quotation marks:

services:
    acme.type.employee:
         class: Acme\AcmeBundle\Form\Type\FormType
         tags:
             - { name: form.type, alias: form_em }
         arguments: ["@doctrine"]
Daniel
  • 76
  • 5