Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2421

Many-To-Many relation creation failed when using non PK entity field

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: Git Master, 2.3.3
    • Fix Version/s: None
    • Component/s: Mapping Drivers, Tools
    • Security Level: All
    • Labels:
    • Environment:
      Ubuntu linux 12.04, php 5.4.9

      Description

      Given these entities :

      /**
       * Class Domain
       *
       * @ORM\Entity
       * @ORM\Table(name="profils_domains")
       */
      class Domain
      {
          /**
           * @var string
           *
           * @ORM\Id
           * @ORM\Column(type="string", length=22, nullable=false)
           */
          protected $name = '';
      }
      
      /**
       * Class Web
       *
       * @ORM\Entity
       * @ORM\Table(name="profils_webs",
       *          uniqueConstraints={@ORM\UniqueConstraint(name="web_unique",columns={"name", "domain"})}
       * )
       */
      class Web
      {
          /**
           * @var integer
           *
           * @ORM\Id
           * @ORM\GeneratedValue
           * @ORM\Column(type="integer", nullable=false)
           */
          protected $id;
      
          /**
           * @var string
           *
           * @ORM\Column(type="string", length=22, nullable=false)
           */
          protected $name = '';
      
          /**
           * @var Domain
           *
           * @ORM\ManyToOne(targetEntity="Domain", fetch="LAZY")
           * @ORM\JoinColumn(name="domain", referencedColumnName="name", nullable=false, onDelete="CASCADE")
           */
          protected $domain;
      }
      
      /**
       * Class WebsGroup
       *
       * @ORM\Entity
       * @ORM\Table(name="profils_websgroups",
       *          uniqueConstraints={@ORM\UniqueConstraint(name="websgroup_unique",columns={"name", "domain"})}
       * )
       */
      class WebsGroup
      {
          /**
           * @var integer
           *
           * @ORM\Id
           * @ORM\GeneratedValue
           * @ORM\Column(type="integer", nullable=false)
           */
          protected $id;
      
          /**
           * @var string
           *
           * @ORM\Column(type="string", length=22, nullable=false)
           */
          protected $name = '';
      
          /**
           * @var Domain
           *
           * @ORM\ManyToOne(targetEntity="Domain", fetch="LAZY")
           * @ORM\JoinColumn(name="domain", referencedColumnName="name", nullable=false, onDelete="CASCADE")
           */
          protected $domain;
      
          /**
           * @var ArrayCollection
           *
           * @ORM\ManyToMany(targetEntity="Web", indexBy="id", fetch="EXTRA_LAZY")
           * @ORM\JoinTable(name="profils_websgroups_webs",
           *      joinColumns={
           * @ORM\JoinColumn(name="websgroup_id", referencedColumnName="id", onDelete="CASCADE"),
           * @ORM\JoinColumn(name="domain", referencedColumnName="domain", onDelete="CASCADE")
           *          },
           *      inverseJoinColumns={
           * @ORM\JoinColumn(name="web_id", referencedColumnName="id", onDelete="CASCADE"),
           * @ORM\JoinColumn(name="domain", referencedColumnName="domain", onDelete="CASCADE")
           *          }
           *      )
           */
          protected $webs;
      }
      

      I've got a domain, some web sites per domain and websgroups which group web sites. I want to be sure in my database that a web group from a domain D can contain only web sites from the very same domain but when calling the console tool for creating my schema it raise :

      [Doctrine\ORM\ORMException]                                                                                                                                      
        Column name `domain` referenced for relation from Entity\WebsGroup towards Entity\Web does not exist. 
      

      It's because domain is already an association to an entity which and is not part of the primary key.

      I've quick fixed getDefiningClass from Doctrine\ORM\Tools\SchemaTool to make it work but i really don't know if it's the proper way :

          private function getDefiningClass($class, $referencedColumnName)
          {
              $referencedFieldName = $class->getFieldName($referencedColumnName);
      
              if ($class->hasField($referencedFieldName)) {
                  return array($class, $referencedFieldName);
              } else if (in_array($referencedColumnName, $class->getIdentifierColumnNames())) {
                  // it seems to be an entity as foreign key
                  foreach ($class->getIdentifierFieldNames() as $fieldName) {
                      if ($class->hasAssociation($fieldName) && $class->getSingleAssociationJoinColumnName($fieldName) == $referencedColumnName) {
                          return $this->getDefiningClass(
                              $this->em->getClassMetadata($class->associationMappings[$fieldName]['targetEntity']),
                              $class->getSingleAssociationReferencedJoinColumnName($fieldName)
                          );
                      }
                  }
              } else if (in_array($referencedColumnName, $class->getAssociationNames())) {
                  return $this->getDefiningClass(
                      $this->em->getClassMetadata($class->associationMappings[$referencedColumnName]['targetEntity']),
                      $class->getSingleAssociationReferencedJoinColumnName($referencedColumnName)
                  );
              }
      
              return null;
          }
      

        Activity

        Hide
        Bavo Janss added a comment -

        I stumbled on this issue when experiencing a similar bug.
        There is something seriously wrong with the referencedColumn in a ManyToMany relationship.
        When you use a PK as 'id' and set your referenced column to 'id' everything is fine.
        But when you use 'productId' as PK and reference it properly creation fails because "column 'id' doens't exists in table", which is very strange. After introducing a bogus column 'id' to the entity, but still referencing 'productId' a linking table is created but it has FK's to 'id' not to productId. When changing the referenced column to 'bogus' the creation also fails because: "column 'bogus' doesn't exists in table".

        To me doctrine checks the the referencedColumn for existence but after that just creates everything assuming the default PK 'id'.

        Show
        Bavo Janss added a comment - I stumbled on this issue when experiencing a similar bug. There is something seriously wrong with the referencedColumn in a ManyToMany relationship. When you use a PK as 'id' and set your referenced column to 'id' everything is fine. But when you use 'productId' as PK and reference it properly creation fails because "column 'id' doens't exists in table", which is very strange. After introducing a bogus column 'id' to the entity, but still referencing 'productId' a linking table is created but it has FK's to 'id' not to productId. When changing the referenced column to 'bogus' the creation also fails because: "column 'bogus' doesn't exists in table". To me doctrine checks the the referencedColumn for existence but after that just creates everything assuming the default PK 'id'.
        Hide
        Benjamin Eberlei added a comment -

        You cannot use a reference column that is not a primary key. Doctrine does not support this.

        Show
        Benjamin Eberlei added a comment - You cannot use a reference column that is not a primary key. Doctrine does not support this.
        Hide
        Bruno CHALOPIN added a comment -

        I've start making a PR and a test case but it is linked to http://www.doctrine-project.org/jira/browse/DDC-2413
        I'm looking in making a proper fix to DDC-2413 first.

        Show
        Bruno CHALOPIN added a comment - I've start making a PR and a test case but it is linked to http://www.doctrine-project.org/jira/browse/DDC-2413 I'm looking in making a proper fix to DDC-2413 first.
        Hide
        Fabio B. Silva added a comment -

        Bruno CHALOPIN Except for some CS this fix seems good.

        If you have time you can send as pull request

        Show
        Fabio B. Silva added a comment - Bruno CHALOPIN Except for some CS this fix seems good. If you have time you can send as pull request

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Bruno CHALOPIN
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: