Skip to content

Commit

Permalink
Merge pull request #6760 from doctrine/fix/#6759-showstopper-one-to-o…
Browse files Browse the repository at this point in the history
…ne-inverse-not-being-loaded-with-correct-identifier-restrictions

#6759 showstopper one-to-one inverse not being loaded with correct identifier restrictions when defining `joinColumn`
  • Loading branch information
lcobucci authored Oct 8, 2017
2 parents 13f838f + 66f903a commit f2dc9a8
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 6 deletions.
10 changes: 4 additions & 6 deletions lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,8 @@ public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifie
$sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
$owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);

$computedIdentifier = [];

// TRICKY: since the association is specular source and target are flipped
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) {
Expand All @@ -800,15 +802,11 @@ public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifie
);
}

// unset the old value and set the new sql aliased value here. By definition
// unset($identifier[$targetKeyColumn] works here with how UnitOfWork::createEntity() calls this method.
$identifier[$targetClass->getFieldForColumn($targetKeyColumn)] =
$computedIdentifier[$targetClass->getFieldForColumn($targetKeyColumn)] =
$sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);

unset($identifier[$targetKeyColumn]);
}

$targetEntity = $this->load($identifier, null, $assoc);
$targetEntity = $this->load($computedIdentifier, null, $assoc);

if ($targetEntity !== null) {
$targetClass->setFieldValue($targetEntity, $assoc['mappedBy'], $sourceEntity);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\OneToOneInverseSideLoad;

use Doctrine\ORM\Mapping as ORM;

/**
* @Entity()
* @Table(name="one_to_one_inverse_side_load_inverse")
*/
class InverseSide
{
/**
* @Id()
* @Column(type="string")
* @GeneratedValue(strategy="NONE")
*/
public $id;

/**
* @OneToOne(targetEntity=OwningSide::class, mappedBy="inverse")
*/
public $owning;
}
29 changes: 29 additions & 0 deletions tests/Doctrine/Tests/Models/OneToOneInverseSideLoad/OwningSide.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\OneToOneInverseSideLoad;

use Doctrine\ORM\Mapping as ORM;

/**
* @Entity()
* @Table(name="one_to_one_inverse_side_load_owning")
*/
class OwningSide
{
/**
* @Id()
* @Column(type="string")
* @GeneratedValue(strategy="NONE")
*/
public $id;

/**
* Owning side
*
* @OneToOne(targetEntity=InverseSide::class, inversedBy="owning")
* @JoinColumn(nullable=false, name="inverse")
*/
public $inverse;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\ORM\Tools\ToolsException;
use Doctrine\Tests\Models\OneToOneInverseSideLoad\InverseSide;
use Doctrine\Tests\Models\OneToOneInverseSideLoad\OwningSide;
use Doctrine\Tests\OrmFunctionalTestCase;

class OneToOneInverseSideLoadAfterDqlQueryTest extends OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();

try {
$this->_schemaTool->createSchema([
$this->_em->getClassMetadata(OwningSide::class),
$this->_em->getClassMetadata(InverseSide::class),
]);
} catch(ToolsException $e) {
// ignored
}
}

/**
* @group 6759
*/
public function testInverseSideOneToOneLoadedAfterDqlQuery(): void
{
$owner = new OwningSide();
$inverse = new InverseSide();

$owner->id = 'owner';
$inverse->id = 'inverse';
$owner->inverse = $inverse;
$inverse->owning = $owner;

$this->_em->persist($owner);
$this->_em->persist($inverse);
$this->_em->flush();
$this->_em->clear();

/* @var $fetchedInverse InverseSide */
$fetchedInverse = $this
->_em
->createQueryBuilder()
->select('inverse')
->from(InverseSide::class, 'inverse')
->andWhere('inverse.id = :id')
->setParameter('id', 'inverse')
->getQuery()
->getSingleResult();

self::assertInstanceOf(InverseSide::class, $fetchedInverse);
self::assertInstanceOf(OwningSide::class, $fetchedInverse->owning);

$this->assertSQLEquals(
'select o0_.id as id_0 from one_to_one_inverse_side_load_inverse o0_ where o0_.id = ?',
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery - 1]['sql']
);

$this->assertSQLEquals(
'select t0.id as id_1, t0.inverse as inverse_2 from one_to_one_inverse_side_load_owning t0 WHERE t0.inverse = ?',
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
);
}
}

0 comments on commit f2dc9a8

Please sign in to comment.