我正在创建一个动态的问题/答案表单。我需要显示给定部分的答案字段集合,这些字段仅与登录用户有关。数据模型是:
部分有很多SectionQuestion(一个部分代表表单的页面) SectionQuestion有一个问题和许多答案 答案有一个用户和一个SectionQuestion
我的表单代码是:
//SectionFormType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('sectionQuestions', 'collection', array(
'type' => new SectionQuestionFormType($this->answerListener),
'label' => false
))
->add('save', 'submit');
}
//SectionQuestionFormType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventSubscriber($this->answerListener);
}
//AnswerListener.php
public function preSetData($event)
{
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
$form->add(
'answers',
'collection',
array(
'type' => new AnswerFormType($data->getQuestion()),
'auto_initialize' => false,
'label' => false,
'required' => false,
)
);
}
//AnswerFormType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$fieldType = $this->question->getAnswerType();
$config = array(
'required' => true,
'label' => $this->question->getText(),
'auto_initialize' => false
);
if ($fieldType == 'choice') {
$valueList = $this->question->getValueList();
$values = $valueList->loadChoiceList();
$config['choice_list'] = $values;
$config['empty_value'] = 'Please select one';
}
$builder->add('answer', $fieldType, $config);
}
这段代码很实用,但不是我真正需要的。我需要在AnswerListener中添加的集合,以提供与当前登录的用户和空白答案相关的现有答案的混合,其中尚未输入答案。
我知道不是在AnswerListener'答案'(它与SectionQuestions中的关系属性匹配)中命名集合字段,我可以将其命名为'filteredAnswers',并在SectionQuestions实体类中编写一个getter / setter返回答案的子集。但!我无法访问Entity类中getter内的登录用户。
我无法将字段类型更改为Entity,因为据我所知,我将无法规定使用AnswerFormType表单,这对于设置答案字段标签至关重要使用我的问题实体的值(实际问题文本)。
在AnswerListener中,我可以使用$ form-> add($ this-> factory-> createNamed(....))并以这种方式提供数据子集(因为我可以访问实体管理器在AnswerListener类中登录用户并执行查询。但!我无法弄清楚如何使这成为一个集合字段类型。我可以使用createNamed来正确显示表单:
$form->add(
$this->factory->createNamed(
'answer',
new AnswerFormType(
$data->getQuestion()),
$answer,
array(
'auto_initialize' => false,
'mapped' => false,
'label' => false
)
)
)
)
...但是!这只会在表单中添加单独的答案字段,因此发布的值永远不会持久保存到数据库中(可能是因为SectionQuestions希望通过未找到的'answers'属性添加它们。)
似乎我在每一个转折点都难过。关于如何让这个工作的任何想法?
答案 0 :(得分:0)
//AnswerListener.php
public function preSetData($event)
{
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
$answerRepository = $this->entityManager
->getRepository('RecruitmentCoreBundle:Answer');
$answer = $answerRepository->findOneBy(
array(
'sectionQuestion_id' => $data->getId(),
'user_id' => $authenticated_user_id
)
);
if(!$answer) {
$answer = null;
}
$form->add(
$this->factory->createNamed(
'answer',
new AnswerFormType($data->getQuestion()),
$answer,
$formOptions = array (
'auto_initialize' => false,
'mapped' => false,
'label' => false,
)
)
);
}
您可以在此处看到我检查数据库以查看登录用户是否已经为给定的SectionQuestion提供了答案。如果有,则传递给createdNamed,如果没有,则传递null并在屏幕上显示空白的答案表单字段。
要保存表单,我有一个如下服务:
//FormService.php
class FormService
{
private $formFactory;
private $entityManager;
private $sectionForm;
/**
* @param FormFactoryInterface $factory
* @param EntityManager $em
* @param SectionFormType $form
*/
public function __construct(
FormFactoryInterface $factory,
EntityManager $em,
SectionFormType $form)
{
$this->formFactory = $factory;
$this->entityManager = $em;
$this->sectionForm = $form;
}
public function generateSectionForm($roundId, $sectionId)
{
$sectionRepository = $this->entityManager
->getRepository('RecruitmentCoreBundle:Section');
$section = $sectionRepository->findOneBy(array('id' => $sectionId));
return $this->formFactory->create($this->sectionForm, $section);
}
public function saveSectionAnswers($form, Section $section)
{
foreach($form['sectionQuestions'] as $sectionQuestion) {
$answer = $sectionQuestion['answer']->getData();
if (null === $answer->getId()) {
$sectionQuestion = $sectionQuestion->getData();
$answer->setSectionQuestion($sectionQuestion);
$answer->setUser(//logged in user);
}
$this->entityManager->persist($answer);
}
$this->entityManager->flush();
return $form;
}
}
即使我使用了映射' =>在AnswerListener.php中的createNamed方法调用中,您可以在我的FormService类的saveSectionAnswers方法中看到$ sectionQuestion [' answer'] - > getData();返回一个Answer对象。这将填充给定的SectionQuestion的已提交表单数据,然后我可以将其保存到数据库中。可能是提供了Answer对象,因为我将Answer实体定义为我的AnswerFormType.php类中的data_class:
//AnswerFormType.php
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Recruitment\CoreBundle\Entity\Answer'
)
);
}
无论如何,它工作并提供我所需的功能。