Symfony 实体持久化查找以前存在的新关系
嗨,我有一个动作,可以将人添加到组中 为了提高可用性,表单将删除组中已有的人员 我的控制器操作如下所示:Symfony 实体持久化查找以前存在的新关系,symfony,doctrine-orm,symfony-forms,Symfony,Doctrine Orm,Symfony Forms,嗨,我有一个动作,可以将人添加到组中 为了提高可用性,表单将删除组中已有的人员 我的控制器操作如下所示: public function addAction(UserGroup $userGroup) { $tempGroup = new UserGroup(); foreach ($userGroup->getUsers() as $user) { $tempGroup->addUser($user); } $f
public function addAction(UserGroup $userGroup)
{
$tempGroup = new UserGroup();
foreach ($userGroup->getUsers() as $user) {
$tempGroup->addUser($user);
}
$form = $this->container->get('form.factory')->create(new UserGroupQuickType(), $tempGroup);
$request = $this->container->get('request');
if ('POST' === $request->getMethod()) {
$form->submit($request);
if ($form->isValid()) {
$group = $form->getData();
/** @var $myUserManager UserManager */
$myUserManager = $this->container->get('strego_user.user_manager');
/** @var $em EntityManager */
$em = $this->container->get('em');
foreach ($group->getUsers() as $toInvite) {
$userGroup->addUser($toInvite);
}
$em->persist($userGroup);
$em->flush($userGroup);
}
}
return array(
'form' => $form->createView(),
'userGroup' => $userGroup
);
}
此代码引发异常:
A new entity was found through the relationship 'Strego\UserBundle\Entity\UserGroup#users'
that was not configured to cascade persist operations for entity: Degi.
To solve this issue: Either explicitly call EntityManager#persist() on
this unknown entity or configure cascade persist this
association in the mapping for example @ManyToOne(..,cascade={"persist"}).
新发现的关系以前就已经存在了。这意味着用户“Degi”已经在组中,并且不是新实体
如果我不使用persist,我可以避免这个错误,但是我会得到一个异常:实体必须为单个计算进行管理或计划删除
这是因为我的“usergroup”实体始终具有实体状态3(=已分离)
对于与我的用户组有1对1关系的实体,我使用了相同的逻辑(与临时组等),从那里我可以轻松地将人员添加到组中。
但这一行动并非如此,它在逻辑上做着完全相同的事情
更新:
我之前的更新方向是错误的。但相比之下,(几乎)相同的控制器工作:
public function addAction(BetRound $betRound)
{
$userGroup = new UserGroup();
foreach ($betRound->getUsers() as $user) {
$userGroup->addUser($user);
}
$form = $this->createForm(new UserGroupQuickType(), $userGroup);
$request = $this->getRequest();
if ('POST' === $request->getMethod()) {
$form->submit($request);
if ($form->isValid()) {
/** @var $betRoundManager BetRoundManager */
$betRoundManager = $this->container->get('strego_tipp.betround_manager');
/** @var $myUserManager UserManager */
$myUserManager = $this->container->get('strego_user.user_manager');
$group = $form->getData();
foreach ($group->getUsers() as $toInvite) {
if (!$betRound->getUserGroup()->hasUser($toInvite)) {
$betRound->getUserGroup()->addUser($toInvite);
}
}
$this->getDoctrine()->getManager()->flush();
return $this->redirect($this->generateUrl('betround_show', array('id' => $betRound->getId())));
}
}
return array(
'form' => $form->createView(),
'betRound' => $betRound
);
}
这是预期的行为,因为您的关系不是新实体,而是非托管对象 迭代时,您可以尝试合并
$toInvite
。别担心,如果您通过表单获取的对象设置了适当的标识符(@Id
)值,它们将从数据库中重新加载,而不是标记为插入。另一方面,新添加的对象将被标记
因此,在尝试任何操作之前,请确保每个旧的$toInvite
都设置了一个ID
foreach ($group->getUsers() as $toInvite) {
$em->merge($toInvite);
$userGroup->addUser($toInvite);
}
// safe to do now, all of the added users are either reloaded or marked for insertion
$em->perist($usetGroup);
$em->flush($userGroup);
希望这能有所帮助。发生这种情况是因为
$userGroup
已经是一个实体,并且$toInvite
是一个新实体,您正在尝试刷新$userGroup
。要使此代码正常工作,您需要在实体文件中指定cascade={“persist”}
(注释或yaml,以您喜欢的为准)
另一种解决方案是执行相反的操作并将$toInvite
foreach ($group->getUsers() as $toInvite) {
$toInvite->setUserGroup($userGroup);
$em->persist($toInvite);
}
$em->flush();
我认为第一种选择是更好的选择经过几次尝试,我发现这个问题实际上有两个问题: 1.我有一个监听器,它更新了persist上的一些行,即使这不是必需的。
2.paramconverter以某种方式分离即将进入的实体。这意味着我的用户组和其中的所有用户都是分离的。一旦它们再次添加到用户组中,这些实体对于EM来说似乎是“新的”。因此,我需要合并所有用户并修复我的侦听器以更新“createdBy”,否则也需要合并。“新”找到的实体不是“toInvite”中的一个,而是旧实体中的一个。那么我也必须合并所有现有的实体吗?$toInvite也是一个已经存在的实体。它是一个现有用户。我只是将组中的一个关系添加到用户。这就是为什么我认为只更新usergroups就足够了。在这种情况下,
cascade={“persist”}
应该可以解决您的问题。如果我将持久化toInvite,它会抛出一个异常,因为toInvite没有被识别为已经存在的实体,然后由于唯一的约束而失败,因为条令需要添加一个新条目,其数据与现有条目相同。