Search code examples
phpdoctrinerelationshipsymfony5

One entity having 2 ManyToOne relations to the same other entity


I'm working with Symfony5. I have 2 entities with relationships, Character and Wedding.

Each Character can have many Wedding. Each Wedding is related to 2 different Character.

/**
 * @ORM\Entity(repositoryClass=CharacterRepository::class)
 */
class Character
{
/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\Column(type="string", length=50, nullable=true)
 */
private $firstName;

/**
 * @ORM\Column(type="string", length=50, nullable=true)
 */
private $lastName;
[...]

And Wedding :

/**
 * @ORM\Entity(repositoryClass=WeddingRepository::class)
 */
class Wedding
{
/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\Column(type="string", length=4, nullable=true)
 */
private $startYear;

/**
 * @ORM\Column(type="string", length=4, nullable=true)
 */
private $endYear;
[...]
}

I tried to set 2 different ManyToOne relations in Wedding entity (persona1 and persona2) but persona1 and persona2 had the same inversedBy="weddings", so it's not working.

I tried 2 ManyToMany relations too, but Doctrine didn't like it :

 // Character
  /**
  * @ORM\ManyToMany(targetEntity=Wedding::class, mappedBy="persona1")
  */
private $weddings1;

/**
 * @ORM\ManyToMany(targetEntity=Wedding::class, mappedBy="persona2")
 */
private $weddings2;
// Wedding

/**
 * @ORM\ManyToMany(targetEntity=Character::class, inversedBy="weddings1")
 */
private $persona1;

/**
 * @ORM\ManyToMany(targetEntity=Character::class, inversedBy="weddings2")
 */
private $persona2;

The mappings App\Entity\Wedding#persona2 and App\Entity\Character#weddings are inconsistent with each other.

What is the good relationship, ManyToOne or ManyToMany, since each Wedding is related to 2 Characters ? How to make it works with Doctrine ?

Thanks for all suggestion !

Ash


Solution

  • I would suggest to have ManyToMany relation between Wedding and Character entities if there is no such specific reason or differentiation between character 1 and character 2

    class Character
    {
        // ...
        
        /**
        * @ORM\ManyToMany(targetEntity=Wedding::class, mappedBy="characters")
        */
        private $weddings;
    }
    
    class Wedding
    {
        // ...
        
        /**
         * @ORM\ManyToMany(targetEntity=Character::class, inversedBy="weddings")
         */
        private $characters;
    }
    

    This way you can scale it in future if you have more characters to be assigned to a wedding

    If there are any strict actions that need to be performed specific to character 1 or character 2 depends on your needs, then you can use OneToMany and ManyToOne as

    class Character
    {
        // ...
    
        /**
         * @ORM\OneToMany(targetEntity=Wedding::class, mappedBy="characterA")
         */
        private $weddingsA;
    
        /**
         * @ORM\OneToMany(targetEntity=Wedding::class, mappedBy="characterB")
         */
        private $weddingsB;
    }
    
    class Wedding
    {
        // ...
    
        /**
         * @ORM\ManyToOne(targetEntity=Character::class, inversedBy="weddingsA")
         */
        private $characterA;
        
        /**
         * @ORM\ManyToOne(targetEntity=Character::class, inversedBy="weddingsB")
         */
        private $characterB;
    }