我有一个Symfony 4项目。 在我的控制器中,我有一个操作来编辑数据库中的对象:
/**
* Editer un groupe
*
* @Route("/admin/validation/{id}", name="admin_validation_edit")
*
* @param GroupeValidateurs $groupeValidateurs
* @return void
*/
public function edit(GroupeValidateurs $groupeValidateurs, Request $request)
{
$form = $this->createForm(GroupeValidateursType::class, $groupeValidateurs);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//persist and flush in database
}
但是当我的表格被提交时,我想比较我的旧对象和我的新对象,以做出一些行动。
为此,我使用了一个会话:
$session = $this->get('session');
if (!$session->has('groupe')) {
$session->set('groupe', $groupeValidateurs);
}
当表格提交并有效时,我会将其删除。
它可以工作,但它是不正确的,因为,如果我进入一个编辑页面与一些groupeValidateur,紧接着,我进入另一个groupeValidateur的另一个编辑页面,我的会话变量将包含我以前的groupeValidateur。
请问我可以使用哪种解决方案?
$form->handleRequest($request)
你的对象$groupeValidateurs
仍然是原始的。
如果您想保留一些信息,有几种选择,其中非常简单明了:
处理外部对象和表单组件外部:
如果我理解正确,您只想阻止添加/删除某些用户。由于我不知道您的实体,我将假设您的对象具有返回当前用户的方法getUsers()
。
$oldUsers = $groupeValidateurs->getUsers(); // I assume $oldUsers is an ARRAY***
$form = $this->createForm(...)
//...
if($form->isSubmitted() && $form->isValid()) {
$newUsers = $groupeValidateurs->getUsers();
// do whatever ...
}
***( 如果这是 OneToMany 或 ManyToMany 关系,请确保返回数组而不是集合:
public function getUsers() {
return $this->users instanceof DoctrineCommonCollectionsCollection
? $this->users->toArray()
: $this->users;
}
如果您设法始终将$this->users
作为Collection
,则可以return $this->users->toArray();
其他选项:
- 将事件侦听器添加到表单中,以便在编辑进入之前捕获数据,将其添加到约束中,该约束获取额外的用户列表以防止添加/删除
- 如果用户身上有一个属性,表明它很清楚,用户永远不应该被删除,你可以把它烘焙到你的add/removeUser函数中:
注意:根据您的表单,您可能需要将by_reference设置为 false。恕我直言,这不是一个真正的问题,如果 a( 您的function removeUser($user) { if($user->isAdmin()) { return; } $this->users->removeElement($user); // I assume users to be a doctrine Collection } function setUsers($users) { foreach($this->users as $user) { if($user->isAdmin() && !in_array($users)) { $users[] = $user; // add user; } } $this->users = $users; }
getUsers()
返回数组而不是集合(它应该如何(或 b( 如果您实现addUser
/removeUser
. 此外,这种方法有一个明显的警告,即没有人可以在不删除管理员权限的情况下删除该用户,所以也许这是矫枉过正 ;o( - 设置原则事件侦听器以更新实体类型,以检查已删除的用户并相应地重新添加它们。 为此,您要么必须以某种方式检查变更集(这可能是矫枉过正(
- 更改对象的用户时,存储用户列表的旧版本(如果添加/删除实现,请注意不要覆盖备份(
- 在您的实体上正确实现
clone
,并在更改对象之前实际生成对象的副本(通过 handleRequest(。 随意比较。 - 获取 Andrea Manzi 描述的原始实体并与之进行比较。
在编辑"操作"中,尝试使用:
if ($form->isSubmitted() && $form->isValid()) {
$currentdata = $form->getData();
/**/
}
获取当前数据的提交
或者编写这样的"更新"操作:
public function update(Request $request, $id)
{
/* @var $em EntityManager */
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository(Entity::class)->find($id); //your GroupeValidateurs entity class
$form = $this->createForm(GroupeValidateursType::class, $groupeValidateurs);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//persist and flush in database
$currentdata = $form->getData();
$beforedata = $em->getUnitOfWork()->getOriginalEntityData($entity);
/*....*/
}
将对象克隆到$cloneGroupeValidateurs。将实体设置为窗体。接下来提交表单并与之前克隆的变量进行比较。