我在 symfony 中更新包含两个实体(“事件”和“信息”)的表单时遇到问题。在用户尝试更新信息之前一切都工作正常。当他们这样做时,所有信息都会保存为新的数据库条目。
public function editAction(Request $request, Event $event)
{
$user = $this->getUser();
$editForm = $this->createFormBuilder()
->setMethod('PUT');
$editForm->add("event", 'AppBundle\Form\EventType');
$editForm->add("info", 'AppBundle\Form\InfoType');
$editForm = $editForm->getForm();
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$formEvent = $editForm->get('event')->getData();
echo "Debug<br />";
echo "form id: ". $formEvent->getId(); // Wrong. Returns null.
echo "<br /> event id: ". $event->getId(); // The correct id of entity that should be updated.
$em->merge($formEvent);
$em->flush();
} else {
$editForm->get('event')->setData($event);
}
return $this->render('event/edit.html.twig', array(
'event' => $event,
'edit_form' => $editForm->createView()
));
我回显一些调试信息,handleRequest() 确实将新信息映射到 $editForm->get('event') 中找到的事件实体中,但缺少 Id,我认为这与创建新实体而不是更新。怎么了?
路由:
event_edit:
path: /{id}/edit
defaults: { _controller: "AppBundle:Event:edit" }
methods: [GET, POST, PUT]
树枝:
{{ form_start(edit_form, {'attr': {'novalidate': 'novalidate'}}) }}
{{ form_errors(edit_form) }}
{{ form_widget(edit_form.event.title) }}
{{ form_widget(edit_form.info) }}
<input type="submit" value="Save" />
{{ form_end(edit_form) }}
如果事件实体是您要更新的实体并且由学说管理(已加载),则需要将事件实体传递到您的表单。试试这个:
public function editAction(Request $request, Event $event)
{
$user = $this->getUser();
$editForm = $this->createFormBuilder($event)
->setMethod('PUT');
$editForm->add("event", 'AppBundle\Form\EventType');
$editForm->add("info", 'AppBundle\Form\InfoType');
$editForm = $editForm->getForm();
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($event);
$em->flush();
}
return $this->render('event/edit.html.twig', array(
'event' => $event,
'edit_form' => $editForm->createView()
));
}
因此,由于我在更新实体时也遇到问题 - 我将为其他人留下信息。
Symfony 版本: 4.3.x
$contact_form = $this->app->forms->contact()->handleRequest($request);
此代码只是返回表单,然后传递请求
public function contact(array $params = [], MyContact $my_contact_type = null): FormInterface {
return $this->createForm(MyContactType::class, $my_contact_type, $params);
}
这不会更新现有表格。您必须将实体作为数据传递(第二个参数)。
现在我又学到了另一件有趣的事情。
我的渲染视图使用 contact_form 和其他表单中的字段,因此我有一个从请求中提取子表单并提交它们的机制。最后我得到了
Request
以及原始表单数据。
所以现在如果你这样做
$form->getData
,你就可以从请求中获得整个实体构建。我修改了我的视图,以便我也填写 ID 表单,因此我拥有数据库中已存在的 100% 相同实体 - 1:1 进行比较。
保留根据请求构建的此类实体将导致创建新实体。 您必须从数据库中获取实体来更新它。
这就是我处理这个案例的方式:
public function saveEntity(MyContact $my_contact, bool $search_and_rebuild_entity = false){
if( $search_and_rebuild_entity ){
$id = $my_contact->getId();
$name = $my_contact->getName();
$contacts = $my_contact->getContacts();
$description = $my_contact->getDescription();
$image_path = $my_contact->getImagePath();
$name_background_color = $my_contact->getNameBackgroundColor();
$description_background_color = $my_contact->getDescriptionBackgroundColor();
$found_entity = $this->find($id);
if( !empty($found_entity) ){
$my_contact = $found_entity;
$my_contact->setName($name);
$my_contact->setContacts($contacts->toJson());
$my_contact->setImagePath($image_path);
$my_contact->setDescription($description);
$my_contact->setNameBackgroundColor($name_background_color);
$my_contact->setDescriptionBackgroundColor($description_background_color);
}
}
$this->_em->persist($my_contact);
$this->_em->flush();
}