我有两个实体 - 用户&挑战。用户可以参与许多挑战,挑战可以有许多参与者(用户)。我开始通过在Users类上创建“多对多”关系来解决此问题:
/**
* @ORM\ManytoMany(targetEntity="Challenge")
* @ORM\JoinTable(name="users_challenges",joinColumns={@ORM\JoinColumn(name="user_id",referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="challenge_id",referencedColumnName="id")})
*
*/
protected $challenges;
然而,我意识到我需要针对用户/挑战组合存储距离属性(用户在挑战中走了多远)。 Doctrine2文档声明:
“为什么多对多关联不太常见?因为经常要将其他属性与关联关联起来,在这种情况下,您会引入关联类。因此,直接的多对多关联会消失并被替换通过3个参与课程之间的一对多/多对一关联。“
所以我的问题是用户,挑战和用户挑战之间的这些关联应该是什么?
的更新 的
有关实体代码的链接,请参阅第一个答案的评论。我有一个控制器方法,它总是创建一个新的UsersChallenges记录,而不是更新现有的记录(这是我想要的)
public function updateUserDistanceAction()
{
$request = $this->getRequest();
$distance = $request->get('distance');
$challenge_id = $request->get('challenge_id');
if($request->isXmlHttpRequest()) {
$em = $this->getDoctrine()->getEntityManager();
$user = $this->get('security.context')->getToken()->getUser();
$existingChallenges = $user->getChallenges();
$challengeToUpdate = $em->getRepository('GymloopCoreBundle:Challenge')
->find( (int) $challenge_id);
if(!$challengeToUpdate) {
throw $this->createNotFoundException('No challenge found');
}
//does the challengeToUpdate exist in existingChallenges? If yes, update UsersChallenges with the distance
//if not, create a new USersChallenges object, set distance and flush
if ( !$existingChallenges->isEmpty() && $existingChallenges->contains($challengeToUpdate)) {
$userChallenge = $em->getRepository('GymloopCoreBundle:UsersChallenges')
->findOneByChallengeId($challengeToUpdate->getId());
$userChallenge->setDistance( $userChallenge->getDistance() + (int) $distance );
$em->flush();
} else {
$newUserChallenge = new UsersChallenges();
$newUserChallenge->setDistance($distance);
$newUserChallenge->setChallenge($challengeToUpdate);
$newUserChallenge->setUser($user);
$user->addUsersChallenges($newUserChallenge);
$em->persist($user);
$em->persist($newUserChallenge);
$em->flush();
}
//if success
return new Response('success');
//else
}
}
答案 0 :(得分:8)
用户(一对多) - > UsersChallenges
UsersChallenges(多对一) - >用户
UsersChallenges(多对一) - >挑战
挑战(一对多) - > UsersChallenges
答案 1 :(得分:1)
我相信你需要在$em->persist($userChallenge);
之前$em->flush();
$userChallenge->setDistance( $userChallenge->getDistance() + (int) $distance );
$em->persist($userChallenge);
$em->flush();
但是我不确定它是否能解决你的问题。
您可以在isEmpty
contains
和existingChallenges
功能吗?
答案 2 :(得分:0)
此代码有效。一个问题是我正在测试UserChallenge集合是否包含一个显然会失败的Challenge对象。
工作代码:
if ( !$existingChallenges->isEmpty() ) {
foreach($existingChallenges as $ec) {
$existingChallengeIdArray[] = $ec->getId();
}
}
if( in_array($challenge_id, $existingChallengeIdArray) ) {
$userChallenge = $em->getRepository('GymloopCoreBundle:UsersChallenges')
->findOneByChallenge($challengeToUpdate->getId());
$userChallenge->setDistance( $userChallenge->getDistance() + (int) $distance );
$em->flush();
} else {
$newUserChallenge = new UsersChallenges();
$newUserChallenge->setDistance($distance);
$newUserChallenge->setChallenge($challengeToUpdate);
$newUserChallenge->setUser($user);
$user->addUsersChallenges($newUserChallenge);
$em->persist($newUserChallenge);
$em->flush();
}