Add tests for extra lazy many-to-many associations
and fixed production code
This commit is contained in:
parent
ba3df8577b
commit
7b9c6a69bd
@ -534,24 +534,28 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$indexBy = $mapping['indexBy'];
|
$indexBy = $mapping['indexBy'];
|
||||||
$id = $this->uow->getEntityIdentifier($collection->getOwner());
|
$id = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||||
|
|
||||||
$targetEntity = $this->em->getClassMetadata($mapping['targetEntity']);
|
$sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
|
||||||
|
$targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
|
||||||
|
|
||||||
if (! $mapping['isOwningSide']) {
|
if ( ! $mapping['isOwningSide']) {
|
||||||
$associationSourceClass = $this->em->getClassMetadata($mapping['targetEntity']);
|
$associationSourceClass = $this->em->getClassMetadata($mapping['targetEntity']);
|
||||||
$mapping = $associationSourceClass->associationMappings[$mapping['mappedBy']];
|
$mapping = $associationSourceClass->associationMappings[$mapping['mappedBy']];
|
||||||
$joinColumns = $mapping['joinTable']['joinColumns'];
|
$joinColumns = $mapping['joinTable']['joinColumns'];
|
||||||
$relationMode = 'relationToTargetKeyColumns';
|
$sourceRelationMode = 'relationToTargetKeyColumns';
|
||||||
|
$targetRelationMode = 'relationToSourceKeyColumns';
|
||||||
} else {
|
} else {
|
||||||
$joinColumns = $mapping['joinTable']['inverseJoinColumns'];
|
|
||||||
$associationSourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
|
$associationSourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
|
||||||
$relationMode = 'relationToSourceKeyColumns';
|
$joinColumns = $mapping['joinTable']['inverseJoinColumns'];
|
||||||
|
$sourceRelationMode = 'relationToSourceKeyColumns';
|
||||||
|
$targetRelationMode = 'relationToTargetKeyColumns';
|
||||||
}
|
}
|
||||||
|
|
||||||
$quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform). ' t';
|
$quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform) . ' t';
|
||||||
$whereClauses = array();
|
$whereClauses = array();
|
||||||
$params = array();
|
$params = array();
|
||||||
|
$types = array();
|
||||||
|
|
||||||
$joinNeeded = !in_array($indexBy, $targetEntity->identifier);
|
$joinNeeded = ! in_array($indexBy, $targetClass->identifier);
|
||||||
|
|
||||||
if ($joinNeeded) { // extra join needed if indexBy is not a @id
|
if ($joinNeeded) { // extra join needed if indexBy is not a @id
|
||||||
$joinConditions = array();
|
$joinConditions = array();
|
||||||
@ -559,21 +563,25 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
foreach ($joinColumns as $joinTableColumn) {
|
foreach ($joinColumns as $joinTableColumn) {
|
||||||
$joinConditions[] = 't.' . $joinTableColumn['name'] . ' = tr.' . $joinTableColumn['referencedColumnName'];
|
$joinConditions[] = 't.' . $joinTableColumn['name'] . ' = tr.' . $joinTableColumn['referencedColumnName'];
|
||||||
}
|
}
|
||||||
$tableName = $this->quoteStrategy->getTableName($targetEntity, $this->platform);
|
$tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform);
|
||||||
$quotedJoinTable .= ' JOIN ' . $tableName . ' tr ON ' . implode(' AND ', $joinConditions);
|
$quotedJoinTable .= ' JOIN ' . $tableName . ' tr ON ' . implode(' AND ', $joinConditions);
|
||||||
|
$columnName = $targetClass->getColumnName($indexBy);
|
||||||
|
|
||||||
$whereClauses[] = 'tr.' . $targetEntity->getColumnName($indexBy) . ' = ?';
|
$whereClauses[] = 'tr.' . $columnName . ' = ?';
|
||||||
$params[] = $key;
|
$params[] = $key;
|
||||||
|
$types[] = Helper::getTypeOfColumn($columnName, $targetClass, $this->em);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
||||||
if (isset($mapping[$relationMode][$joinTableColumn])) {
|
if (isset($mapping[$sourceRelationMode][$joinTableColumn])) {
|
||||||
|
$column = $mapping[$sourceRelationMode][$joinTableColumn];
|
||||||
|
|
||||||
$whereClauses[] = 't.' . $joinTableColumn . ' = ?';
|
$whereClauses[] = 't.' . $joinTableColumn . ' = ?';
|
||||||
$params[] = $id[$targetEntity->getFieldForColumn($mapping[$relationMode][$joinTableColumn])];
|
$params[] = $id[$targetEntity->getFieldForColumn($mapping[$relationMode][$joinTableColumn])];
|
||||||
} elseif (!$joinNeeded) {
|
} elseif (!$joinNeeded) {
|
||||||
$whereClauses[] = 't.' . $joinTableColumn . ' = ?';
|
$whereClauses[] = 't.' . $joinTableColumn . ' = ?';
|
||||||
$params[] = $key;
|
$params[] = $key;
|
||||||
|
$types[] = Helper::getTypeOfColumn($column, $targetClass, $this->em);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +594,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($quotedJoinTable, $whereClauses, $params);
|
return array($quotedJoinTable, $whereClauses, $params, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -618,6 +626,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform);
|
$quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform);
|
||||||
$whereClauses = array();
|
$whereClauses = array();
|
||||||
$params = array();
|
$params = array();
|
||||||
|
$types = array();
|
||||||
|
|
||||||
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
||||||
$whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?';
|
$whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?';
|
||||||
@ -625,6 +634,11 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
|
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
|
||||||
$params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
|
$params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
|
||||||
|
|
||||||
|
$params[] = $targetClass->containsForeignIdentifier
|
||||||
|
? $targetId[$targetClass->getFieldForColumn($column)]
|
||||||
|
: $targetId[$targetClass->fieldNames[$column]];
|
||||||
|
$types[] = Helper::getTypeOfColumn($column, $targetClass, $this->em);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\ValueConversionType;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="vct_inversed_manytomany_extralazy")
|
||||||
|
*/
|
||||||
|
class InversedManyToManyExtraLazyEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Column(type="rot13")
|
||||||
|
* @Id
|
||||||
|
*/
|
||||||
|
public $id1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToMany(
|
||||||
|
* targetEntity="OwningManyToManyExtraLazyEntity",
|
||||||
|
* mappedBy="associatedEntities",
|
||||||
|
* fetch="EXTRA_LAZY",
|
||||||
|
* indexBy="id2"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public $associatedEntities;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->associatedEntities = new ArrayCollection();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\ValueConversionType;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="vct_owning_manytomany_extralazy")
|
||||||
|
*/
|
||||||
|
class OwningManyToManyExtraLazyEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Column(type="rot13")
|
||||||
|
* @Id
|
||||||
|
*/
|
||||||
|
public $id2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToMany(
|
||||||
|
* targetEntity="InversedManyToManyExtraLazyEntity",
|
||||||
|
* inversedBy="associatedEntities",
|
||||||
|
* fetch="EXTRA_LAZY",
|
||||||
|
* indexBy="id1"
|
||||||
|
* )
|
||||||
|
* @JoinTable(
|
||||||
|
* name="vct_xref_manytomany_extralazy",
|
||||||
|
* joinColumns={@JoinColumn(name="owning_id", referencedColumnName="id2")},
|
||||||
|
* inverseJoinColumns={@JoinColumn(name="inversed_id", referencedColumnName="id1")}
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public $associatedEntities;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->associatedEntities = new ArrayCollection();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\ValueConversionType;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type as DBALType;
|
||||||
|
use Doctrine\Tests\Models\ValueConversionType as Entity;
|
||||||
|
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entities all use a custom type that converst the value as identifier(s).
|
||||||
|
* {@see \Doctrine\Tests\DbalTypes\Rot13Type}
|
||||||
|
*
|
||||||
|
* Test that ManyToMany associations work correctly, focusing on EXTRA_LAZY
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* @group DDC-3380
|
||||||
|
*/
|
||||||
|
class ManyToManyExtraLazyTest extends OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
if (DBALType::hasType('rot13')) {
|
||||||
|
DBALType::overrideType('rot13', 'Doctrine\Tests\DbalTypes\Rot13Type');
|
||||||
|
} else {
|
||||||
|
DBALType::addType('rot13', 'Doctrine\Tests\DbalTypes\Rot13Type');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->useModelSet('vct_manytomany_extralazy');
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$inversed1 = new Entity\InversedManyToManyExtraLazyEntity();
|
||||||
|
$inversed1->id1 = 'abc';
|
||||||
|
|
||||||
|
$inversed2 = new Entity\InversedManyToManyExtraLazyEntity();
|
||||||
|
$inversed2->id1 = 'def';
|
||||||
|
|
||||||
|
$owning1 = new Entity\OwningManyToManyExtraLazyEntity();
|
||||||
|
$owning1->id2 = 'ghi';
|
||||||
|
|
||||||
|
$owning2 = new Entity\OwningManyToManyExtraLazyEntity();
|
||||||
|
$owning2->id2 = 'jkl';
|
||||||
|
|
||||||
|
$inversed1->associatedEntities->add($owning1);
|
||||||
|
$owning1->associatedEntities->add($inversed1);
|
||||||
|
$inversed1->associatedEntities->add($owning2);
|
||||||
|
$owning2->associatedEntities->add($inversed1);
|
||||||
|
|
||||||
|
$inversed2->associatedEntities->add($owning1);
|
||||||
|
$owning1->associatedEntities->add($inversed2);
|
||||||
|
$inversed2->associatedEntities->add($owning2);
|
||||||
|
$owning2->associatedEntities->add($inversed2);
|
||||||
|
|
||||||
|
$this->_em->persist($inversed1);
|
||||||
|
$this->_em->persist($inversed2);
|
||||||
|
$this->_em->persist($owning1);
|
||||||
|
$this->_em->persist($owning2);
|
||||||
|
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function tearDownAfterClass()
|
||||||
|
{
|
||||||
|
$conn = static::$_sharedConn;
|
||||||
|
|
||||||
|
$conn->executeUpdate('DROP TABLE vct_xref_manytomany_extralazy');
|
||||||
|
$conn->executeUpdate('DROP TABLE vct_owning_manytomany_extralazy');
|
||||||
|
$conn->executeUpdate('DROP TABLE vct_inversed_manytomany_extralazy');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatTheExtraLazyCollectionFromOwningToInversedIsCounted()
|
||||||
|
{
|
||||||
|
$owning = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyExtraLazyEntity',
|
||||||
|
'ghi'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $owning->associatedEntities->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatTheExtraLazyCollectionFromInversedToOwningIsCounted()
|
||||||
|
{
|
||||||
|
$inversed = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyExtraLazyEntity',
|
||||||
|
'abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $inversed->associatedEntities->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatTheExtraLazyCollectionFromOwningToInversedContainsAnEntity()
|
||||||
|
{
|
||||||
|
$owning = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyExtraLazyEntity',
|
||||||
|
'ghi'
|
||||||
|
);
|
||||||
|
|
||||||
|
$inversed = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyExtraLazyEntity',
|
||||||
|
'abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue($owning->associatedEntities->contains($inversed));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatTheExtraLazyCollectionFromInversedToOwningContainsAnEntity()
|
||||||
|
{
|
||||||
|
$inversed = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyExtraLazyEntity',
|
||||||
|
'abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
$owning = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyExtraLazyEntity',
|
||||||
|
'ghi'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue($inversed->associatedEntities->contains($owning));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatTheExtraLazyCollectionFromOwningToInversedContainsAnIndexbyKey()
|
||||||
|
{
|
||||||
|
$owning = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyExtraLazyEntity',
|
||||||
|
'ghi'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue($owning->associatedEntities->containsKey('abc'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatTheExtraLazyCollectionFromInversedToOwningContainsAnIndexbyKey()
|
||||||
|
{
|
||||||
|
$inversed = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyExtraLazyEntity',
|
||||||
|
'abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue($inversed->associatedEntities->containsKey('ghi'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatASliceOfTheExtraLazyCollectionFromOwningToInversedIsLoaded()
|
||||||
|
{
|
||||||
|
$owning = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyExtraLazyEntity',
|
||||||
|
'ghi'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertCount(1, $owning->associatedEntities->slice(0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatASliceOfTheExtraLazyCollectionFromInversedToOwningIsLoaded()
|
||||||
|
{
|
||||||
|
$inversed = $this->_em->find(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyExtraLazyEntity',
|
||||||
|
'abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertCount(1, $inversed->associatedEntities->slice(1, 1));
|
||||||
|
}
|
||||||
|
}
|
@ -242,6 +242,10 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyCompositeIdForeignKeyEntity',
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyCompositeIdForeignKeyEntity',
|
||||||
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyCompositeIdForeignKeyEntity'
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyCompositeIdForeignKeyEntity'
|
||||||
),
|
),
|
||||||
|
'vct_manytomany_extralazy' => array(
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\InversedManyToManyExtraLazyEntity',
|
||||||
|
'Doctrine\Tests\Models\ValueConversionType\OwningManyToManyExtraLazyEntity'
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -457,6 +461,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
$conn->executeUpdate('DELETE FROM vct_auxiliary');
|
$conn->executeUpdate('DELETE FROM vct_auxiliary');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->_usedModelSets['vct_manytomany_extralazy'])) {
|
||||||
|
$conn->executeUpdate('DELETE FROM vct_xref_manytomany_extralazy');
|
||||||
|
$conn->executeUpdate('DELETE FROM vct_owning_manytomany_extralazy');
|
||||||
|
$conn->executeUpdate('DELETE FROM vct_inversed_manytomany_extralazy');
|
||||||
|
}
|
||||||
|
|
||||||
$this->_em->clear();
|
$this->_em->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user