【问题标题】:How should this Many-To-Many doctrine2 association be defined?应该如何定义这种多对多原则2 关联?
【发布时间】:2011-10-11 06:41:40
【问题描述】:

我有两个实体 - 用户和挑战。一个用户可以参与许多挑战,一个挑战可以有许多参与者(用户)。我开始通过在我的 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

      }

    }

【问题讨论】:

    标签: php mysql doctrine-orm


    【解决方案1】:

    用户(一对多)-> 用户挑战

    UsersChallenges(多对一)-> 用户

    UsersChallenges(多对一)-> 挑战

    挑战(一对多)-> 用户挑战

    【讨论】:

    【解决方案2】:

    我相信你在$em->flush();之前想要一个$em->persist($userChallenge);

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

    但是我不确定它是否能解决您的问题。

    你能在existingChallenges中发布isEmptycontains函数吗

    【讨论】:

      【解决方案3】:

      此代码有效。一个问题是我正在测试一个 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();
      
              }
      

      【讨论】:

        猜你喜欢
        • 2013-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多