How to define this many-to-many relationship doctrine2?

I have two entities - users and problems. A user can participate in many problems, and a task can have many participants (users). I began to approach this problem by creating a Many-to-Many relationship in the Users class:

/** * @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; 

However, I realized that I needed to keep the distance attribute against the user / call combination (how far the user made the call). Doctrine2 docs say:

“Why are many-to-many associations less common? Because you often want to associate additional attributes with an association, you enter an association class in this case. Therefore, the direct many-to-many association disappears and is replaced by one-to-many associations -many / many-to-one "between 3 participating classes."

So my question is, what kind of associations should these be between User, Challenge and UsersChallenges?

UPDATE

See the comment on the first answer for links to Entity code. I have a controller method, below which a new UsersChallenges record is always created, and not the existing one is updated (what I want)

 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 } } 
+6
source share
3 answers

I believe you want $em->persist($userChallenge); to $em->flush();

 $userChallenge->setDistance( $userChallenge->getDistance() + (int) $distance ); $em->persist($userChallenge); $em->flush(); 

However, I'm not sure if your problem solves.

Can you send the function isEmpty and contains to existingChallenges

+1
source

User (one-to-many) → MembersChallenges

UsersChallenges (many-to-one) -> User

UsersChallenges (many-to-one) → Challenge

Challenge (one-to-many) → Users

+8
source

This code worked. One of the problems was that I tested if the UserChallenge collection contains a Challenge object, which obviously fails.

Work code:

 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(); } 
0
source

Source: https://habr.com/ru/post/899021/


All Articles