Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-3169

ManyToMany association fails when joining on a single column of a composity key

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.4.2
    • Fix Version/s: None
    • Component/s: ORM
    • Security Level: All

      Description

      I have two entities with a ManyToMany association between them. The first entity Campsite has a composite key (campsiteID, year). The second entity Region has a single key (regionID).
      I want to create an association between Campsite::campsiteID and Region::regionID. See the entities below.

      Campsite
      /**
       * @ORM\Table(name="Campsite")
       */
      class Campsite
      {
          /**
           * @ORM\Id
           * @ORM\Column(name="campsiteID", type="integer", precision=0, nullable=false)
           */
          protected $campsiteID;
      
          /**
           * @ORM\Id
           * @ORM\Column(name="year", type="smallint", precision=0, nullable=false)
           */
          protected $year;
      
          /**
           * @ORM\ManyToMany(targetEntity="AcsiGeo\Entity\Region", fetch="EAGER", cascade={"detach"})
           * @ORM\JoinTable(name="CampsiteRegion",
           *   joinColumns={
           *     @ORM\JoinColumn(name="campsiteID", referencedColumnName="campsiteID", nullable=false)
           *   },
           *   inverseJoinColumns={
           *     @ORM\JoinColumn(name="regionID", referencedColumnName="regionID", nullable=false)
           *   }
           * )
           * @var \Doctrine\Common\Collections\ArrayCollection $regions
           */
          protected $regions;
      }
      
      Region
      /**
       * @ORM\Table(name="Region")
       */
      class Region
      {
          /**
           * @ORM\Id
           * @ORM\GeneratedValue(strategy="IDENTITY")
           * @ORM\Column(name="regionID", type="integer", precision=0, nullable=false)
           */
          protected $regionID;
      }
      

      I run the following code to persist a new one.

      $campsite = new Campsite();
      $campsite->setCampsiteID(111111);
      $campsite->setYear(2014);
      
      $region = new Region();
      $region->setRegionID(1);
      $campsite->addRegion($region);
      
      $em->persist($region);
      $em->persist($campsite);
      $em->flush();
      

      This results in a record added to the CampsiteRegion table:

      campsiteID : 2014
      regionID: 1

      This is clearly wrong as the value of the year field is added to the campsiteID column.

      While debugging the problem I've found an issue with the method to determine the params in ManyToManyPersister on line 147.
      The following code pops the last identifier from the array of identifiers.

      $params[] = $isRelationToSource ? array_pop($identifier1) : array_pop($identifier2);
      

      In my case:

      array(
          'campsiteID' => 111111,
          'year' => 2014
      )
      

      Which picks 2014 as the value to use.
      When I change the code to get the actual column from the array everything works as expected.

      $params[] = $isRelationToSource ? $identifier1[$joinTableColumn] : $identifier2[$joinTableColumn];
      

      I am not 100% sure if this change will have some side effects / edge case I'm not aware of.

      For the time being I have fixed the problem bij just reversing the properties in my class, but this is not a real fix of course.

        Activity

        There are no comments yet on this issue.

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Bram Gerritsen
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: