我有两个实体;
Element具有自引用关系,ElementAnswer与Element具有一对多关系(一个元素可以有多个ElementAnswers)。
我正在使用带有嵌入式集合的Symfony2,它正在运行(与javasript一起)。我可以添加多个孩子'父母的元素'元件。我也可以为子元素添加多个答案。但是..当我添加一个子元素并添加子元素的答案时,只有子元素被持久化。答案(这是对子元素的嵌入式集合)不会被持久化。当我编辑整个集合时,答案会持续存在。 为了更精确,我做了一些截图,我调试了帖子数据。这是完全一样的。
的ElementType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('question')
//->add('answers')
->add('answers', 'collection', array(
'entry_type' => new AnswerType(),
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
'empty_data' => null,
))
->add('conditions', 'collection', array(
'entry_type' => new ConditionalType(),
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
'empty_data' => null,
))
//->add('children', )
->add('children', 'collection', array(
'entry_type' => new ElementChildType(),
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
'empty_data' => null,
))
;
}
ElementChildType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('answers', 'collection', array(
'entry_type' => new AnswerType(),
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
'empty_data' => null,
'block_name' => 'child_element_answer',
'prototype_name' => '__child_element_answer__',
))
;
}
这是我提交之前表单的样子: (子元素1和2已经保留。子元素3是表单中新添加的实体 这是帖子数据:
element[name]:parent-element-name
element[question]: blabla
element[children][0][name]:child element 1
element[children][0][answers][0][name]:child answer 1-1
element[children][1][name]:child element 2
element[children][1][answers][0][name]:child answer 2-1
element[children][2][name]:child element 3
element[children][2][answers][0][name]:child answer 3-1
element[_token]:xxxxxxxxxxxxxxxxxxxxxxxxxxxx
这是提交后表单的样子: (如您所见:子元素3中没有子代答案)
当我现在添加一个孩子答案(提交后)时,孩子的答案会被持久化。正在调用相同的控制器和相同的实体,所以我被卡住了。请帮忙。谢谢!
修改
我终于按照以下方式编辑了我的控制器。可能不是最好的做法,但它正在工作,所以我想我应该让你知道:
/**
* Displays a form to edit an existing Element entity.
*
* @Route("/{id}/edit", name="element_edit")
* @Method({"GET", "POST"})
*/
public function editAction(Request $request, Element $element, $firstPost = NULL)
{
$em = $this->getDoctrine()->getManager();
$deleteForm = $this->createDeleteForm($element);
$editForm = $this->createForm('AppBundle\Form\ElementType', $element);
$editForm->handleRequest($request);
$breadcrumbs = array();
$breadcrumbs[] = array("name" => "Dashboard", "url" => $this->get("router")->generate("dashboard"));
$breadcrumbs[] = array("name" => "Elementen lijst", "url" => $this->get("router")->generate("element_index"));
$breadcrumbs[] = array("name" => "Element bewerken");
if ($editForm->isSubmitted() && $editForm->isValid()) {
$originalChildren = new ArrayCollection();
$postChildren = new ArrayCollection();
$newChildren = new ArrayCollection();
foreach ($element->getChildren() as $child) {
$originalChildAnswers = new ArrayCollection();
$originalChildren->add($child);
foreach ($child->getAnswers() as $childAnswer) {
$originalChildAnswers->add($childAnswer);
}
}
if (isset($request->request->get('element')['children'])) {
foreach ($request->request->get('element')['children'] as $postChild) {
$postChildren->add($postChild);
}
}
$newElements = [];
$i = 0;
foreach ($originalChildren as $child) {
if (null != $child->getId() && $element->getChildren()->contains($child)) {
$i++;
} else {
$newElements[] = $i;
$i++;
}
}
foreach ($newElements as $newElement) {
$newChildren->set($newElement, $postChildren[$newElement]);
}
foreach ($newChildren as $key => $newchild) {
foreach ($newchild['answers'] as $newChildAnswer) {
$childAnswerKey = $element->getChildren()->getKeys()[$key];
$answerEntity = new Answer();
$answerEntity->setName($newChildAnswer['name']);
$element->getChildren()[$childAnswerKey]->addAnswer($answerEntity);
}
}
$em->persist($element);
$em->flush();
return $this->redirectToRoute('element_edit', array('id' => $element->getId()));
}
return $this->render('element/edit.html.twig', array(
'breadcrumbs' => $breadcrumbs,
'element' => $element,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}