Symfony2 - 嵌入式表单,不需要修改父级

时间:2013-06-10 20:40:50

标签: forms symfony

我有点设计绑定。我有一系列问题,我希望用户输入每个问题的分数。问题和分数之间存在1:*关系,但在此特定表单上,用户应该只能为每个问题输入一个分数。那么,我如何创建一个自动将分数链接到每个问题的表单类型,例如:

1. blah blah blah?  Score: // user enters a score
2. blah blah blah?  Score: // user enters a score
etc.

由于NDA,我无法透露我的实体,但是可以说,问题在1方面,而得分在*方面。我可以使用Question::getScores()Question::setScores($scores)Score::getQuestion()Score::setQuestion($question)也是如此。

如果这是直接的PHP,那就没问题了。 Symfony2的表单组件有点复杂,所以我不确定如何继续。

1 个答案:

答案 0 :(得分:1)

您想要完成的是为当前用户提交的表单中的每个问题创建一个Score对象。

要完成此操作,请首先为Score对象创建表单类型。

<?php
// src/Acme/Bundle/Form/Type/ScoreType.php
// ...
$builder->add('ranking', 'integer')

这将允许您的应用程序通过表单创建Score对象。

现在,在您的问题表单类型中,您需要嵌入一个未映射的分数表单(由于下面讨论的原因),即

<?php
// src/Acme/Bundle/Form/Type/QuestionType.php
// ...
$builder->add('question')
$builder->add('score', new ScoreType(), array('mapped'=>false))

我假设你目前有类似的设置,除了你可能在ScoreType上使用'scores'上的集合类型。但是,如果当前用户想要看到此表单,那么您不希望显示集合。您只想显示一个,即附加到当前用户的那个。 Symfony无法知道这种逻辑,因为它特定于您的业务逻辑。

这是事件发生的地方。请参阅http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

我的方法是将EventSubscriber绑定到Question表单。您可能应该收听PRE_SET_DATA事件和SUBMIT事件。

您的PRE_SET_DATA侦听器应检查传入的Question对象,以获取有关应将其放入“得分”表单的得分的信息。例如,如果将实体管理器注入您的订户,您可能会询问EM此用户是否已针对此特定问题获得分数,如果是,请抓住并将其作为数据放入“分数”。如果没有,请创建一个新的空白Score对象并将其与此问题和当前用户相关联。

现在,提交表单后,请收听SUBMIT并使用score对象执行逻辑操作。这就是为什么我们不将它映射到问题,因为它是1:*。我们的表格是1:1。这些事件是您进行连接的逻辑。在POST_SUBMIT期间,您可以获取Score对象并使用表单的数据调用$ score-&gt; setQuestion()。

我意识到这是一个有点模糊和有点匆忙的回答,但我希望它能引导你朝着正确的方向前进。