Details
-
Type:
Bug
-
Status:
Resolved
-
Priority:
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:
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);
<?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; } }
<?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; } }
<?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
$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']]);
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.
"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.