开发者

How should this Many-To-Many doctrine2 association be defined?

开发者 https://www.devze.com 2023-04-12 07:48 出处:网络
I have two Entities - Users & Challenges. A User can participate in many challenges and a challenge can have many participants (users). I began approaching this problem by creating a Many-To-Many

I have two Entities - Users & Challenges. A User can participate in many challenges and a challenge can have many participants (users). I began approaching this problem by creating a Many-To-Many relationship on my 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 then realised that I need to store a distance attribute against a user/challenge combination (how far the user has travelled in their challenge). The Doctrine2 docs state:

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

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

UPDATE

See comment to first answer for links to the Entity code. I have a controller method below which always creates a new UsersChallenges record rather than updating an existing one (which is 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('succes开发者_StackOverflow社区s');

       //else

      }

    }


User (one-to-many) -> UsersChallenges

UsersChallenges (many-to-one) -> User

UsersChallenges (many-to-one) -> Challenge

Challenge (one-to-many) -> UsersChallenges


i belive you want a $em->persist($userChallenge); before $em->flush();

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

However i am not sure if it solves your problem.

Can you post isEmpty and contains function in existingChallenges


This code worked. One issue was that I was testing whether a UserChallenge collection contained a Challenge object which would obviously fail.

Working 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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号