Как должна быть определена эта ассоциация многие-ко-многим doctrine2?

#php #mysql #doctrine-orm

#php #mysql #doctrine-orm

Вопрос:

У меня есть две сущности — Пользователи и проблемы. Пользователь может участвовать во многих задачах, а в задаче может быть много участников (пользователей). Я начал подходить к этой проблеме, создав отношение многие-ко-многим в моем классе Users:

 /**
     * @ORMManytoMany(targetEntity="Challenge")
     * @ORMJoinTable(name="users_challenges",joinColumns={@ORMJoinColumn(name="user_id",referencedColumnName="id")},
     * inverseJoinColumns={@ORMJoinColumn(name="challenge_id",referencedColumnName="id")})
     *
     */

    protected $challenges;
  

Однако затем я понял, что мне нужно сохранить атрибут расстояния для комбинации пользователь / вызов (как далеко пользователь продвинулся в своем вызове). В документах Doctrine2 указано:

«Почему ассоциации многие-ко-многим встречаются реже? Поскольку часто требуется связать дополнительные атрибуты с ассоциацией, в этом случае вы вводите класс ассоциации. Следовательно, прямая связь многие-ко-многим исчезает и заменяется ассоциациями один-ко-многим / многие-к-одному между 3 участвующими классами «.

Итак, мой вопрос в том, какими должны быть эти ассоциации между User, Challenge и UsersChallenges?

Обновить

Ссылки на код сущности см. В комментарии к первому ответу. У меня есть метод контроллера ниже, который всегда создает новую запись 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() amp;amp; $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

      }

    }
  

Ответ №1:

Пользователь (один-ко-многим) -> Пользовательские вызовы

Пользовательские вызовы (многие-к-одному) -> Пользователь

Пользовательские вызовы (многие-к-одному) -> Вызов

Вызов (один ко многим) -> Пользовательские вызовы

Комментарии:

1. Спасибо. Для вас это нормально? gist.github.com/1280574 , gist.github.com/1280576 , gist.github.com/1280579

Ответ №2:

я полагаю, вы хотите $em->persist($userChallenge); , чтобы перед $em->flush();

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

Однако я не уверен, решает ли это вашу проблему.

Можете ли вы публиковать isEmpty и contains функционировать в existingChallenges

Ответ №3:

Этот код сработал. Одна из проблем заключалась в том, что я проверял, содержит ли коллекция UserChallenge объект вызова, который, очевидно, потерпит неудачу.

Рабочий код:

 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();

        }