可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
in my Symfony 3-master project, I use this code to create a form in a controller:
$form = $this->createForm(ApplicantType::class, $applicant);
Now I decided to make a service out of this form, so I can use EntityManager inside of it. So in Symfony2.x, this would be pretty easy, just with a declaration in services.yml and this line of code:
$form = $this->createForm($this->get("applicant.form"), $applicant);
However, this is no longer possible in Symfony 3, because this first parameter expect a string, not the form itself.
So my question is: How do I create a form as a service in Symfony 3, or is there any other way how to pass EntityManager inside of the form?
Thank you for any help!
回答1:
Defining a form type as service does not imply passing the instance retrieved from to container to createForm
. when doing this, the container is not involved as far as the form component is involved.
To use a form type registered as a service (with the form.type
tag so that the form component knows about it), you just just reference it by its name (i.e. the fully qualified class name in Symfony 2.8+ and the type name in older versions) in createForm
or in FormBuilder::add
.
This is exactly what you do for Symfony core types btw (text
, choice
and so on), which are registered as services.
the code of your controller does not change at all when using the form type as a service rather than having a form type without dependency and registered implicitly on first usage.
回答2:
This is what i did to inject a form as a service in Symfony 3 from my Symfony 2 Code.
In my service.yml i changed
issue.form:
class: Gutersohn\Bundle\CoreBundle\Form\IssueType
arguments: ['@service_container']
tags:
- { name: form.type, alias: issue }
to
issue.form:
class: Gutersohn\Bundle\CoreBundle\Form\IssueType
arguments: ['@service_container']
tags:
- { name: form.type }
In my controller i changed
$form = $this->container->get('form.factory')->create($this->container->get('issue.form'), $issue, [
"method" => "post",
"action" => $this->container->get('router')->generate("ticket_add")
]);
to
$form = $this->container->get('form.factory')->create(IssueType::class, $issue, [
"method" => "post",
"action" => $this->container->get('router')->generate("ticket_add")
]);
回答3:
In issue #17013 on GitHub, aliemre stated:
Adding form.type tag is enough in your service definition.
app.form.corporation_type:
class: App\CorporationBundle\Form\CorporationType
arguments: ["@doctrine.orm.entity_manager"]
tags:
- { name: form.type }
Controller should remain same:
$form = $this->createForm(CorporationType::class, $corporation);
I've tested and it works!
回答4:
I tried to look into the problem and I dig into the change in github, which is this one:
https://github.com/symfony/symfony/commit/abca2d6fdc89479586e052cd11241d5a9bc885e5#diff-5c1348d69be32426ff20446c9e812365R64
Then I found the PR into Symfony which has this BC removal, I decided to ask why the reason and you can see it here:
https://github.com/symfony/symfony/pull/16075#issuecomment-165106123
I hope this helps you with the concept around it!
回答5:
On symfony 3.4, you can easily create a service to, for example, inject EntityManager in your form :
class addDiverseType extends AbstractType
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
Then, you have to "transform" your form as service in the service.yml file :
form.add_diverse:
class: PlatformBundle\Form\addDiverseType
arguments: ['@doctrine.orm.entity_manager']
tags:
- { name: form.type }
Finally, you call your form in the controller :
$form = $this->createForm(addDiverseType::class, $parameter);