+3 votes

Similarly to common assocation, directions on many to many assoc are handled by aliases.

As you can see in following examples, based on these aliases you can control how your association should looks like. It's because Doctrine2 handles associations based on the aliases.

In all next examples I will use following model:

Skipper many to many ORM model

In case you fill only alias to inverse entity, you will get unidirectional (one-way) association heading from first to second entity. As export, you will get:

 @ORM\ManyToMany(targetEntity="First")
 @ORM\JoinTable(
     name="mn",
     joinColumns={@ORM\JoinColumn(name="second_id", referencedColumnName="id", nullable=false)},
     inverseJoinColumns={@ORM\JoinColumn(name="first_id", referencedColumnName="id", nullable=false)}
 )

Skipper one-way association

In case you fill only alias to owner entity, you will get incorrect unidirectional (one-way) association heading from second to first. I'm writing incorrect, because this isn't correct Doctrine2 configuration and based on the ERD modelling it's not possible to create such association without helper table. In this situation you will get:

 @ORM\ManyToMany(targetEntity="Second", mappedBy=)

Skipper one-way association

In case you fill both aliases, you get bidirectional association (two-way) between first and second entity. In this case, Skipper exports annotations to both entities:

 SecondEntity:
  @ORM\ManyToMany(targetEntity="First", inversedBy="second")
  @ORM\JoinTable(
     name="mn",
     joinColumns={@ORM\JoinColumn(name="second_id", referencedColumnName="id", nullable=false)},
     inverseJoinColumns={@ORM\JoinColumn(name="first_id", referencedColumnName="id", nullable=false)}
  )
  private $first; 

 FirstEntity:
 @ORM\ManyToMany(targetEntity="Second", mappedBy="first")
 private $second; 

Skipper two-way association

Hope these examples will help you understand the concept of creating many to many association on our application.

in How To & Manuals by Skipper developer (141k points)
recategorized by

Thanks Ludek,

In regards to exporting to Doctrine2 annotations, the First inverse entity has a blank annotation referencing the Second owner entity. Is this expected behaviour? As when generating getters and setters, and associated documentation it will add confusion as programmers could assume bi-directional

For example, the First entity:

 /**
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

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

/**
 * 
 */
private $second;

This is expected behavior in case you create MN-association with two aliases, export the project to the annotations and then removed one alias and export the project again.

If you create new MN-association directly with single alias only, Skipper correctly generates only single variable without the $second one.

But if the code is generated for MN-association with both aliases, Skipper generated both variables and both annotations. After you have removed the alias, Skipper removes only annotations and not variables.

This is correct behavior in the annotations format. Skipper cannot know this variable wasn't used anywhere else in the code, because Skipper imports and analyses only ORM mapping. ORM mapping is defined by annotations only and because of that Skipper never changes anything else than annotations when updating/removing code. Only exception is adding new variables because this is a safe action.

So in your case if you removed alias, you need to manually remove the variable from the code to achieve perfectly clean and clear code, but Skipper cannot do this automatically because of the security reasons.

Please log in or register to answer this question.