Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-1080

AbstractHydrator ->_gatherRowData using wrong metadata info

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Git Master
    • Fix Version/s: 2.1
    • Component/s: Mapping Drivers, ORM
    • Security Level: All
    • Labels:
      None

      Description

      The following worked in a previous version but after upgrading to the latest to fix the security issue, I got an issue.

      I will first start with the setup:

      MySQL
      CREATE TABLE `bar` (
        `barID` int(11) NOT NULL AUTO_INCREMENT,
        `barTitle` varchar(45) DEFAULT NULL,
        PRIMARY KEY (`barID`)
      ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
      
      CREATE TABLE `foo` (
        `fooID` int(11) NOT NULL AUTO_INCREMENT,
        `fooTitle` varchar(45) DEFAULT NULL,
        PRIMARY KEY (`fooID`)
      ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
      
      CREATE TABLE `fooBar` (
        `fooID` int(11) NOT NULL,
        `barID` int(11) NOT NULL,
        `orderNr` int(11) DEFAULT NULL,
        PRIMARY KEY (`fooID`,`barID`),
        KEY `b` (`barID`),
        KEY `f` (`fooID`),
        CONSTRAINT `f` FOREIGN KEY (`fooID`) REFERENCES `foo` (`fooID`) ON DELETE CASCADE ON UPDATE NO ACTION,
        CONSTRAINT `b` FOREIGN KEY (`barID`) REFERENCES `bar` (`barID`) ON DELETE CASCADE ON UPDATE NO ACTION
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      INSERT INTO `bar` (barID,barTitle) VALUES (1,'bar title 1');
      INSERT INTO `bar` (barID,barTitle) VALUES (2,'bar title 2');
      INSERT INTO `bar` (barID,barTitle) VALUES (3,'bar title 3');
      INSERT INTO `bar` (barID,barTitle) VALUES (4,'bar title 4');
      
      INSERT INTO `foo` (fooID,fooTitle) VALUES (1,'foo title 1');
      INSERT INTO `foo` (fooID,fooTitle) VALUES (2,'foo title 2');
      
      INSERT INTO `fooBar` (fooID,barID,orderNr) VALUES (1,1,0);
      INSERT INTO `fooBar` (fooID,barID,orderNr) VALUES (1,2,1);
      INSERT INTO `fooBar` (fooID,barID,orderNr) VALUES (1,3,3);
      
      Foo.php
      <?php
      /**
       * @Entity
       * @Table(name="foo")
       */
      
      class Application_Model_Foo
      {
      	
      	/**
      	 * @Id 
      	 * @Column(name="fooID", type="integer")
      	 * @GeneratedValue(strategy="AUTO")
      	 */
      	protected $_fooID;
      	
      	/**
      	 * @Column(name="fooTitle", type="string")
      	 */
      	protected $_fooTitle;
      	
      	/**
      	 * @OneToMany(targetEntity="Application_Model_FooBar", mappedBy="_foo",
      	 * cascade={"persist"})
      	 * @OrderBy({"_orderNr"="ASC"})
      	 */
      	protected $_fooBars;
      
      	public function __construct ()
      	{
      		$this->_fooBars = new \Doctrine\Common\Collections\ArrayCollection();
      	}
      	
      	/**
      	 * @return the $fooID
      	 */
      	public function getFooID ()
      	{
      		return $this->_fooID;
      	}
      
      	/**
      	 * @return the $fooTitle
      	 */
      	public function getFooTitle ()
      	{
      		return $this->_fooTitle;
      	}
      
      	/**
      	 * @return the $fooBars
      	 */
      	public function getFooBars ()
      	{
      		return $this->_fooBars;
      	}
      
      	/**
      	 * @param field_type $fooID
      	 */
      	public function setFooID ($fooID)
      	{
      		$this->_fooID = $fooID;
      	}
      
      	/**
      	 * @param field_type $fooTitle
      	 */
      	public function setFooTitle ($fooTitle)
      	{
      		$this->_fooTitle = $fooTitle;
      	}
      
      	/**
      	 * @param field_type $fooBars
      	 */
      	public function setFooBars ($fooBars)
      	{
      		$this->_fooBars = $fooBars;
      	}
      
      
      }
      
      Bar.php
      <?php
      /**
       * @Entity
       * @Table(name="bar")
       */
      
      class Application_Model_Bar
      {
      	
      	/**
      	 * @Id 
      	 * @Column(name="barID", type="integer")
      	 * @GeneratedValue(strategy="AUTO")
      	 */
      	protected $_barID;
      	
      	/**
      	 * @Column(name="barTitle", type="string")
      	 */
      	protected $_barTitle;
      	
      	/**
      	 * @OneToMany(targetEntity="Application_Model_FooBar", mappedBy="_bar",
      	 * cascade={"persist"})
      	 * @OrderBy({"_orderNr"="ASC"})
      	 */
      	protected $_fooBars;
      
      	public function __construct ()
      	{
      		$this->_fooBars = new \Doctrine\Common\Collections\ArrayCollection();
      	}
      	/**
      	 * @return the $barID
      	 */
      	public function getBarID ()
      	{
      		return $this->_barID;
      	}
      
      	/**
      	 * @return the $barTitle
      	 */
      	public function getBarTitle ()
      	{
      		return $this->_barTitle;
      	}
      
      	/**
      	 * @return the $fooBars
      	 */
      	public function getFooBars ()
      	{
      		return $this->_fooBars;
      	}
      
      	/**
      	 * @param field_type $barID
      	 */
      	public function setBarID ($barID)
      	{
      		$this->_barID = $barID;
      	}
      
      	/**
      	 * @param field_type $barTitle
      	 */
      	public function setBarTitle ($barTitle)
      	{
      		$this->_barTitle = $barTitle;
      	}
      
      	/**
      	 * @param field_type $fooBars
      	 */
      	public function setFooBars ($fooBars)
      	{
      		$this->_fooBars = $fooBars;
      	}
      
      
      }
      
      FooBar.php
      <?php
      /**
       * @Table(name="fooBar")
       * @Entity
       */
      class Application_Model_FooBar
      {
      
      	/**
      	 * @ManyToOne(targetEntity="Application_Model_Foo")
      	 * @JoinColumn(name="fooID", referencedColumnName="fooID")
      	 * @Id
      	 */
      	protected $_foo = null;
      
      	/**
      	 * @ManyToOne(targetEntity="Application_Model_Bar")
      	 * @JoinColumn(name="barID", referencedColumnName="barID")
      	 * @Id
      	 */
      	protected $_bar = null;
      
      	/**
      	 * @var integer orderNr
      	 * @Column(name="orderNr", type="integer", nullable=false)
      	 */
      	protected $_orderNr = null;
      
      	/**
      	 * Retrieve the foo property
      	 *
      	 * @return Application_Model_Foo
      	 */
      	public function getFoo()
      	{
      		return $this->_foo;
      	}
      
      	/**
      	 * Set the foo property
      	 *
      	 * @param Application_Model_Foo $foo
      	 * @return Application_Model_FooBar
      	 */
      	public function setFoo($foo)
      	{
      		$this->_foo = $foo;
      		return $this;
      	}
      
      	/**
      	 * Retrieve the bar property
      	 *
      	 * @return Application_Model_Bar
      	 */
      	public function getBar()
      	{
      		return $this->_bar;
      	}
      
      	/**
      	 * Set the bar property
      	 *
      	 * @param Application_Model_Bar $bar
      	 * @return Application_Model_FooBar
      	 */
      	public function setBar($bar)
      	{
      		$this->_bar = $bar;
      		return $this;
      	}
      
      	/**
      	 * Retrieve the orderNr property
      	 *
      	 * @return integer|null
      	 */
      	public function getOrderNr()
      	{
      		return $this->_orderNr;
      	}
      
      	/**
      	 * Set the orderNr property
      	 *
      	 * @param integer|null $orderNr
      	 * @return Application_Model_FooBar
      	 */
      	public function setOrderNr($orderNr)
      	{
      		$this->_orderNr = $orderNr;
      		return $this;
      	}
      
      
      }
      

      When I execute the following code

      IndexController.php
      $foo = $this->_em->find('Application_Model_Foo', 1);
      $fooBars = $foo->getFooBars();
      var_dump(count($fooBars));
      

      I expect "3" as output. But I get "1".

      There seems to be an issue with the metadata or the used fieldname in the _gatherRowData in the AbstractHydrator.

      The following is a dump of $classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$cache[$key]['dqlAlias']]);

      abstractHydrator
      Doctrine\ORM\Mapping\ClassMetadata Object
      (
          [reflFields] => Array
              (
                  [_orderNr] => ReflectionProperty Object
                      (
                          [name] => _orderNr
                          [class] => Application_Model_FooBar
                      )
      
                  [_foo] => ReflectionProperty Object
                      (
                          [name] => _foo
                          [class] => Application_Model_FooBar
                      )
      
                  [_bar] => ReflectionProperty Object
                      (
                          [name] => _bar
                          [class] => Application_Model_FooBar
                      )
      
              )
      
          [_prototype:Doctrine\ORM\Mapping\ClassMetadata:private] => 
          [name] => Application_Model_FooBar
          [namespace] => 
          [rootEntityName] => Application_Model_FooBar
          [customRepositoryClassName] => 
          [isMappedSuperclass] => 
          [parentClasses] => Array
              (
              )
      
          [subClasses] => Array
              (
              )
      
          [namedQueries] => Array
              (
              )
      
          [identifier] => Array
              (
                  [0] => _foo
                  [1] => _bar
              )
      
          [inheritanceType] => 1
          [generatorType] => 5
          [fieldMappings] => Array
              (
                  [_orderNr] => Array
                      (
                          [fieldName] => _orderNr
                          [type] => integer
                          [length] => 
                          [precision] => 0
                          [scale] => 0
                          [nullable] => 
                          [unique] => 
                          [columnName] => orderNr
                      )
      
              )
      
          [fieldNames] => Array
              (
                  [orderNr] => _orderNr
              )
      
          [columnNames] => Array
              (
                  [_orderNr] => orderNr
              )
      
          [discriminatorValue] => 
          [discriminatorMap] => Array
              (
              )
      
          [discriminatorColumn] => 
          [table] => Array
              (
                  [name] => fooBar
              )
      
          [lifecycleCallbacks] => Array
              (
              )
      
          [associationMappings] => Array
              (
                  [_foo] => Array
                      (
                          [fieldName] => _foo
                          [id] => 1
                          [joinColumns] => Array
                              (
                                  [0] => Array
                                      (
                                          [name] => fooID
                                          [referencedColumnName] => fooID
                                          [unique] => 
                                          [nullable] => 1
                                          [onDelete] => 
                                          [onUpdate] => 
                                          [columnDefinition] => 
                                      )
      
                              )
      
                          [cascade] => Array
                              (
                              )
      
                          [inversedBy] => 
                          [targetEntity] => Application_Model_Foo
                          [fetch] => 2
                          [type] => 2
                          [mappedBy] => 
                          [isOwningSide] => 1
                          [sourceEntity] => Application_Model_FooBar
                          [isCascadeRemove] => 
                          [isCascadePersist] => 
                          [isCascadeRefresh] => 
                          [isCascadeMerge] => 
                          [isCascadeDetach] => 
                          [sourceToTargetKeyColumns] => Array
                              (
                                  [fooID] => fooID
                              )
      
                          [joinColumnFieldNames] => Array
                              (
                                  [fooID] => fooID
                              )
      
                          [targetToSourceKeyColumns] => Array
                              (
                                  [fooID] => fooID
                              )
      
                          [orphanRemoval] => 
                      )
      
                  [_bar] => Array
                      (
                          [fieldName] => _bar
                          [id] => 1
                          [joinColumns] => Array
                              (
                                  [0] => Array
                                      (
                                          [name] => barID
                                          [referencedColumnName] => barID
                                          [unique] => 
                                          [nullable] => 1
                                          [onDelete] => 
                                          [onUpdate] => 
                                          [columnDefinition] => 
                                      )
      
                              )
      
                          [cascade] => Array
                              (
                              )
      
                          [inversedBy] => 
                          [targetEntity] => Application_Model_Bar
                          [fetch] => 2
                          [type] => 2
                          [mappedBy] => 
                          [isOwningSide] => 1
                          [sourceEntity] => Application_Model_FooBar
                          [isCascadeRemove] => 
                          [isCascadePersist] => 
                          [isCascadeRefresh] => 
                          [isCascadeMerge] => 
                          [isCascadeDetach] => 
                          [sourceToTargetKeyColumns] => Array
                              (
                                  [barID] => barID
                              )
      
                          [joinColumnFieldNames] => Array
                              (
                                  [barID] => barID
                              )
      
                          [targetToSourceKeyColumns] => Array
                              (
                                  [barID] => barID
                              )
      
                          [orphanRemoval] => 
                      )
      
              )
      
          [isIdentifierComposite] => 1
          [containsForeignIdentifier] => 1
          [idGenerator] => Doctrine\ORM\Id\AssignedGenerator Object
              (
              )
      
          [sequenceGeneratorDefinition] => 
          [tableGeneratorDefinition] => 
          [changeTrackingPolicy] => 1
          [isVersioned] => 
          [versionField] => 
          [reflClass] => ReflectionClass Object
              (
                  [name] => Application_Model_FooBar
              )
      
      )
      

      $fieldName = $this->_rsm->metaMappings[$key]; is "fooID" or "barID"

      After assigning $cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName); you get false back.

      So you check for fooID / barID in the array

      [identifier] => Array
              (
                  [0] => _foo
                  [1] => _bar
              )
      

      what of course is false because they aren't in the array.

      When I set the flag $cache[$key]['isIdentifier'] to true for the 2 fields, I get an output of 3 as expected.

      So the fieldname is wrong or the identifier list is wrong.

        Activity

        Hide
        Benjamin Eberlei added a comment - - edited

        "In a previous version"? What exact version please? I can't pin down the commits with such a broad statement.

        Edit: Ah you are working with master and fk+pk support. Can you still find out the version? There were some general fixes in the hydrator and one larger refactoring since I merged the fk+pk branch.

        Show
        Benjamin Eberlei added a comment - - edited "In a previous version"? What exact version please? I can't pin down the commits with such a broad statement. Edit: Ah you are working with master and fk+pk support. Can you still find out the version? There were some general fixes in the hydrator and one larger refactoring since I merged the fk+pk branch.
        Hide
        Van Hauwaert Bert added a comment -

        This is the last log on a server where it is still working:
        ORM:

        commit 180078d0f6fa97bf5f3398e8c5d2f56030236c33
        Author: Guilherme Blanco <guilhermeblanco@gmail.com>
        Date:   Mon Mar 14 01:04:50 2011 -0300
        
            Added namedQueries as optional during serialization of ClassMetadata.
        

        Common:

        commit ba63ae0f0b6b62a2a8617f01386698730ff2b713
        Author: Jonathan H. Wage <jonwage@gmail.com>
        Date:   Wed Feb 16 10:17:48 2011 -0600
        
            Revert "Adding Driver interface for mapping drivers."
        

        DBAL:

        commit ae084d9c6975356f8f0f10d8802abe91df45b739
        Author: Benjamin Eberlei <kontakt@beberlei.de>
        Date:   Sun Jan 30 10:58:14 2011 -0500
        
            Release {$version}
        
        Show
        Van Hauwaert Bert added a comment - This is the last log on a server where it is still working: ORM: commit 180078d0f6fa97bf5f3398e8c5d2f56030236c33 Author: Guilherme Blanco <guilhermeblanco@gmail.com> Date: Mon Mar 14 01:04:50 2011 -0300 Added namedQueries as optional during serialization of ClassMetadata. Common: commit ba63ae0f0b6b62a2a8617f01386698730ff2b713 Author: Jonathan H. Wage <jonwage@gmail.com> Date: Wed Feb 16 10:17:48 2011 -0600 Revert "Adding Driver interface for mapping drivers." DBAL: commit ae084d9c6975356f8f0f10d8802abe91df45b739 Author: Benjamin Eberlei <kontakt@beberlei.de> Date: Sun Jan 30 10:58:14 2011 -0500 Release {$version}
        Hide
        Benjamin Eberlei added a comment -

        Ah i know what the problem might be.

        Show
        Benjamin Eberlei added a comment - Ah i know what the problem might be.
        Hide
        Van Hauwaert Bert added a comment -

        Great! Looking forward for a fix. It would solve a lot of issues I'm having now.

        Show
        Van Hauwaert Bert added a comment - Great! Looking forward for a fix. It would solve a lot of issues I'm having now.
        Hide
        Benjamin Eberlei added a comment -

        The bug appears because you rename the id column from the default value. If you rename the property to $fooId instead of $_fooId it works.

        I have to check how i can fix this issue, but its complicated.

        Show
        Benjamin Eberlei added a comment - The bug appears because you rename the id column from the default value. If you rename the property to $fooId instead of $_fooId it works. I have to check how i can fix this issue, but its complicated.
        Hide
        Benjamin Eberlei added a comment -

        There are two potential fixes for this bug, both have their drawbacks, we have to discuss them in the team. For now rename the field to the name of the column to get it working.

        Show
        Benjamin Eberlei added a comment - There are two potential fixes for this bug, both have their drawbacks, we have to discuss them in the team. For now rename the field to the name of the column to get it working.
        Hide
        Benjamin Eberlei added a comment -

        Not a blocker, there is a workaround

        Show
        Benjamin Eberlei added a comment - Not a blocker, there is a workaround
        Hide
        Benjamin Eberlei added a comment -

        Fixed

        Show
        Benjamin Eberlei added a comment - Fixed

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Van Hauwaert Bert
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: