Reputation: 494
Short question: How can I inject the EntityManager into embedded form types in symfony2 3.0+? Note: I mentioned embedded form types, not just the parent form
Long question: In previous versions of Symfony2 (<2.6) I found myself in the need of the following: I have an entity A which has an entity B which has an entity C, each entity has it's own form and in each entity form type I have the need to use the entity manager.
In previous versions I did the following in the controller:
$em = $this->getDoctrine()->getManager();
$a = new A();
$form = $this->createForm(new AType($em), $a);
Then in the AType I was able to use the $em in the constructor and continue to pass it down to the childs:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('b', new BType($this->em))
;
}
And in BType.php I would do the same in the buildForm to pass the $em to CType.
The problem I am facing now is that in order for you to define embedded forms in symfony2 3.0+ you have to do something like this:
$form = $this->createForm(AType::class, $a);
Doing it this way without having access to the controller leaves me only (that I know of) with one option, defining the form as a service. With this option I have 2 problems, one is that as they specify in their documentation this should be used if the form is going to be used in several parts of your application, in this case this form is just going to be on one section of the application and I have that A-B-C hierarchy in order to have a proper database structure (something like a Company > Owner > Employee relationship). My other concern is that if I define the form as a service I am aware that I can use:
$form = $this->createForm('servicename', $a);
in the controller and that would inject the EntityManager, but what about BType and CType, how could I inject the EntityManager into them using AType as a service?
My last idea/attempt that I think is very ugly is defining A,B,C as a service and building the form in the controller.
Upvotes: 3
Views: 589
Reputation: 494
OK I figured this out with @Cerad
app.form.a:
class: AppBundle\Form\AType
arguments: ["@doctrine.orm.entity_manager"]
tags:
- { name: form.type, alias: app.form.a }
app.form.b:
class: AppBundle\Form\BType
arguments: ["@doctrine.orm.entity_manager"]
tags:
- { name: form.type, alias: app.form.b }
app.form.c:
class: AppBundle\Form\CType
arguments: ["@doctrine.orm.entity_manager"]
tags:
- { name: form.type, alias: app.form.c }
And then in the controller when you call:
$form = $this->createForm(AType::class, $a);
Apparently Symfony2 in the background looks for the service and injects the dependencies, my confusion was that before you had to call the service yourself when using createForm... I did not see any documentation about this..
Then, in the types when you do:
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('b', BType::class)
;
}
Symfony will take care of injecting the dependencies of BType as well if you define it as a service.
Thanks @Cerad! your comment made me perform this test!
Upvotes: 2