Doctrine: Relación muchos a muchos con campos extras
18 de abril del 2017
En el supuesto de tener una relación muchos a muchos (N-M) entre dos entidades cualesquiera y necesitar campos extras en la la tabla intermedia de dicha relación. Para esto se puede crear una entidad intermedia con dos relaciones uno a muchos (1-N) a las dos entidades originarias.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * * * @ORM\Table(name="participants") * @ORM\Entity(repositoryClass="AppBundle\Repository\ParticipantsRepository") */ class Participants { /** * @var integer * * @ORM\Column(name="nid", type="bigint") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") * */ private $nid; /** * @var string * * @ORM\Column(name="name", type="string", length=100, nullable=true) */ private $name; /** * Bidirectional - uno a muchos (INVERSE SIDE) Para poner atributos extras en una relación N-M * * @ORM\OneToMany(targetEntity="ParticipantsHasAwards", mappedBy="participant", cascade={"all"}) * */ private $participantHasAwards; ////////Incluir Getters y Setters de la entidad } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * * @ORM\Table(name="participants_has_awards") * @ORM\Entity(repositoryClass="AppBundle\Repository\ParticipantsHasAwardsRepository") */ class ParticipantsHasAwards { /** * Bidirectional - muchos a uno (OWNING SIDE) * * * @ORM\Id * @ORM\ManyToOne(targetEntity="Participants", inversedBy="participantHasAwards") * @ORM\JoinColumn(name="par_id", referencedColumnName="nid", * columnDefinition="bigint COMMENT 'Un participante podrá tener muchos premios'", nullable=false, onDelete="CASCADE") * */ private $participant; /** * Bidirectional - muchos a uno (OWNING SIDE) * * * @ORM\Id * @ORM\ManyToOne(targetEntity="Awards", inversedBy="awardHasParticipants") * @ORM\JoinColumn(name="awa_id", referencedColumnName="nid", * columnDefinition="bigint COMMENT 'Un premio se le otorga a muchos participantes'", nullable=false,) * */ private $award; /** * @var string * * @ORM\Column(name="synchronized", type="smallint", nullable=true, options={ * "comment":"Para marcar si ya ha sido sincronizado"}) */ private $synchronized; /** * Al recuperar el objeto desde Participants, se devuelve __toString con el nombre del premio * */ public function __toString() { try { return $this->getAward()->getName(); } catch (Exception $exception) { return ''; } } ////////Incluir Getters y Setters de la entidad } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * * * @ORM\Table(name="award") * @ORM\Entity() */ class Awards { /** * @var integer * * @ORM\Column(name="nid", type="bigint") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") * */ private $nid; /** * @var string * * @ORM\Column(name="name", type="string", length=250) */ private $name; /** * Bidirectional - uno a muchos (INVERSE SIDE) Para poner atributos extras en una relación N-M * * @ORM\OneToMany(targetEntity="ParticipantsHasAwards", mappedBy="award", cascade={"all"}) * */ private $awardHasParticipants; ////////Incluir Getters y Setters de la entidad } |
Saludos desde Colombia, creo que esto es lo que necesitaba para un modelado que estoy realizando, pero antes de aplicarlo desearía presentar mi caso, espero que sea similar.
Tengo las siguientes entidades
Persona
Familia
Donde una Familia puede llegar a tener muchas personas, siendo casa persona única en cada familia ademas una persona solo puede tener una familia, ahora esto lo quiero representar mediante una tabla intermedia o como tu lo llamas campos extra ya que en la tabla intermedia tengo almacenados que rol cumple la persona en la familia (Hijo, Padre, Madre, Abuelo, Tio, ETC)..
Podrías darme una mano con esto..
Gracias.. y de nuevo un gran saludo desde Colombia.
Parce! Gracias por comentar…
Entiendo que cada persona sólo pertenece a una única familia, es es así… No veo necesario usar esa tabla intermedia, ya que es una relación del tipo; peoples (0,n) < => families (0,1). Por tanto, debes poner el campo rol en la tabla peoples.
Otra cosa sería que cada persona pudiera estar en varias familias, en ese caso si sería una relación N-M.
Ya me dices si te vale así.
Saludos!
Y.
Caramba, «Parce» : Colombiano.. ??
Jajaja, claro pero es necesario conocer cuales es el rol de la persona en cada familia.
Persona
id
Familia
id
FamiliaPersona
rol_persona
No se si fui claro… Gracias por responder…
Vale. Entonces si haces eso es porque una persona puede pertenecer a varias familias, eso es una relación N-M. Por tanto, necesitas hacer lo que explico en el post.
El campo que yo llamo $synchronized es tu campo rol_persona, en tu entidad intermedia. Tu Persona, podría ser mi Participants y tu Familia… mi Awards.
PD: Soy español, pero de islas Canarias y aquí hay muchos latino. Además, «Parce» no paraba de escucharlo en la serie «El cartel de lo sapos». jeje
Jajaja, buena (Cartel de los Sapos)… Pues nada voy a desarrollar de esa forma la asociación como me lo dices… y controlaré que una persona no pueda estar en mas de una familia al tiempo, mediante lógica en mi aplicación..
Aunque la otra opción es ingresar el Rol de la persona en la familia en la entidad persona creo que sería más lógico…
Muchas Gracias…
Esperemos pueda avanzar en mi desarrollo…..
Con trabajo, seguro que sale. Un saludo!
Saludos, Yone, hice lo que me sugerías, puse el campo rol en la entidad persona y usé una relación de uno a muchos entre familia y persona.
y usé tu ejemplo para otro caso que se me presentó, aún no he enviado a ningún registro a la base de datos porque sigo adicionando entidades y creando las asociaciones, espero este FDS poder hacer una prueba..
Gracias..
Genial! Yo veía que, para el caso tuyo, era factible esa implementación.
Saludos!
Yone..
Saludos de nuevo
Sabes no se si esto sea posible.. deseo crear una controladora de donde hereden las controladoras que yo desarrollo, ya que siempre necesito verificar el token que se envía, entones para no repetir el método y para no desarrollar un servicio quisiera hacer una clase Controller de donde hereden mis controladoras..
no se si me hago entender y en esa clase hay un método que siempre en cada llamado Http verifica el token y si hay tiene permisos lo deja seguir a hacer el método correspondiente, de lo contrario regresa un JsonResponse con un mensaje donde muestra que no se tiene permisos o algo parecido.
Gracias…
Hola Ronald, por alguna razón no había visto tu comentario. Lo solucionaste?
Saludos!