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
}
}
Gracias. ¿Te parecen bien? https://gist.github.com/1280574, https://gist.github.com/1280576, https://gist.github.com/1280579 – codecowboy