2011-10-11 11 views
6

Tengo dos entidades: usuarios & Desafíos. Un usuario puede participar en muchos desafíos y un desafío puede tener muchos participantes (usuarios). Empecé a abordar este problema mediante la creación de un Muchos-A-Muchos relación en mi clase de usuarios:¿Cómo se debe definir esta asociación Many-To-Many doctrine2?

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

Sin embargo, luego se dio cuenta de que necesito para almacenar un atributo de distancia contra una combinación usuario/desafío (hasta qué punto el usuario ha viajado en su desafío). Doctrine2 docs estado:

"¿Por qué son muchas las asociaciones de muchos a muchos? Porque con frecuencia desea asociar atributos adicionales con una asociación, en cuyo caso se introduce una clase de asociación. En consecuencia, la directa de muchos a muchas asociaciones desaparecen y son reemplazadas por asociaciones uno a muchos/muchos a uno entre las 3 clases participantes ".

Entonces mi pregunta es, ¿qué deberían ser estas asociaciones entre el Usuario, Desafío y Desafíos de los Usuarios?

ACTUALIZACIÓN

Ver comentario a la primera respuesta para enlaces con el código de entidad. Tengo un método de control por debajo del cual siempre se crea un nuevo registro UsersChallenges en lugar de actualizar una ya existente (que es lo que quiero)

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 

     } 

    } 

Respuesta

1

i ser vive quieres un $em->persist($userChallenge); antes $em->flush();

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

Sin embargo no estoy seguro de si se resuelve su problema.

Se puede publicar isEmpty y contains función en existingChallenges

8

usuario (uno-a-muchos) -> UsersChallenges

UsersChallenges (muchos-a-uno) -> usuario

UsersChallenges (muchos-a-uno) -> Desafío

reto (de uno a muchos) -> UsersChallenges

+0

Gracias. ¿Te parecen bien? https://gist.github.com/1280574, https://gist.github.com/1280576, https://gist.github.com/1280579 – codecowboy

0

Este código funcionó. Un problema fue que estaba probando si una colección UserChallenge contenía un objeto Challenge que obviamente fallaría.

código de trabajo:

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

     } 
Cuestiones relacionadas