1

I am trying to create a many-to-many foreign key table relation targeting the same entity.

I have successfully created relations with other entities but I'm having trouble when targeting the same entity.

I read a few stack overflow questions and answers and saw what I was doing was possible.. I based my class of this example - the table unit_relations is empty when i add a parent, but works when I add a child to a unit. I'm assuming because the field has the inversedBy annotation.

What do I need to add to allow bi-drectional updating/inserting?

I tried swapping the joinColums like this answer - nothing...

--

 /**
 * Unit
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Acme\DemoBundle\Entity\UnitRepository")
 */
class Unit
{
   ....

   /**
     * @ORM\ManyToMany(targetEntity="Unit",  inversedBy="parents")
     * @ORM\JoinTable(name="unit_relations",
     *     joinColumns={@ORM\JoinColumn(name="unit_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="child_unit_id", referencedColumnName="id")}
     * )
     */
    private $children;

    /**
     * @ORM\ManyToMany(targetEntity="Unit",  mappedBy="children")
     */
    private $parents;
}

is adding inversedBy instead of having mappedBy, with the join columns also swapped, the proper way to do it?

Can someone explain this?

/**
     * @ORM\ManyToMany(targetEntity="Unit",  inversedBy="parents")
     * @ORM\JoinTable(name="unit_relations",
     *     joinColumns={@ORM\JoinColumn(name="unit_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="child_unit_id", referencedColumnName="id")}
     * )
     */
    private $children;

    /**
     * @ORM\ManyToMany(targetEntity="Unit",  inversedBy="children")
     * @ORM\JoinTable(name="unit_relations",
     *     joinColumns={@ORM\JoinColumn(name="child_unit_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="unit_id", referencedColumnName="id")}
     * )
     */
    private $parents;

EDIT

as requested here's the code showing how I create the relation. I just realized it may because the entity doesn't have an id yet since I'm adding the relation on its creation...

$unit = new \Acme\DemoBundle\Entity\Unit();
/* @var $parentUnit \Acme\DemoBundle\Entity\Unit */
$parentUnit = $this->getDoctrine()->getRepository('AcmeDemoBundle:Unit')->findById($request->get('unitId'));
$unit->addParent($parentUnit);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($unit);
$entityManager->flush();
Community
  • 1
  • 1
StrikeForceZero
  • 2,379
  • 1
  • 25
  • 36
  • What exactly is the problem/error? – RoToRa Jun 25 '14 at 09:41
  • @RoToRa my first snippet only allows you to add a unit to a relation if you add it as a child. if you add it as a parent it doesn't update the join table. so i found out with my second snippet; by changing `mappedBy` to `inversedBy` it would work bidrectional but it doesn't seem to be the "proper" way. I'm seeking clarification on why it works or if there is a proper alternative i'm missing – StrikeForceZero Jun 25 '14 at 10:00
  • Can you show the code you use the add a unit to the relation (both as a child and as a parent)? – RoToRa Jun 25 '14 at 10:23
  • @RoToRa I've added the code, but I'm starting to wonder if its because the entity hasn't been persisted yet and flushed to the database so it doesn't have an ID yet.. – StrikeForceZero Jun 25 '14 at 10:34
  • Yes, that's a good assumption. Does the same code with when adding a child? In any case, try persisting and flushing the new unit first. Also did you remember to initalize the ArrayCollections for both `$children` and `$parent` in the entity constructor? – RoToRa Jun 25 '14 at 11:25

1 Answers1

1

It doesn't matter, that there is no ID, when you add a parent relations.

I cant in detail explain why this happens, but i think the main problem is, that in Many-To-Many Self-Referencing the attribute with JoinTable annotation is potentially the Master-Entity. You can say, that it "holds" all other relations to this Entity.

You can recieve the bi-directional updating/inserting while changing the function $unit->addParent($parent). Change it as follows:

  public function addParent($parent)
  {
      $this->parents[] = $parent;
      $parent->addChild($this); // Add the relation in the proper way
  }

That should work fine!

Regards!

tjoussen
  • 61
  • 4
  • interesting. Although, in my opinion I think having the extra annotations and allowing the entities getter and setters to be auto generated is more cleaner. – StrikeForceZero Jun 26 '14 at 04:44
  • after playing around, the annotations were causing `table already exists` exception when doing a `schema:update`. So this is the proper way – StrikeForceZero Jun 26 '14 at 15:17