Skip to content

Commit

Permalink
Fix association mapping with enum fields
Browse files Browse the repository at this point in the history
  • Loading branch information
michnovka committed Dec 7, 2022
1 parent aeed977 commit cf726a3
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/Doctrine/ORM/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -2812,6 +2812,10 @@ public function createEntity($className, array $data, &$hints = [])
$joinColumnValue = $data[$srcColumn] ?? null;

if ($joinColumnValue !== null) {
if ($joinColumnValue instanceof BackedEnum) {
$joinColumnValue = $joinColumnValue->value;
}

if ($targetClass->containsForeignIdentifier) {
$associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue;
} else {
Expand Down
67 changes: 67 additions & 0 deletions tests/Doctrine/Tests/Models/GH10132/Complex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\GH10132;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\Tests\Models\Enums\Suit;

/** @Entity */
class Complex
{
/**
* @Id
* @Column(type = "string", enumType = Suit::class)
*/
protected Suit $type;

/**
* @Id
* @Column(type = "integer")
*/
protected int $number;

/** @OneToMany(targetEntity = ComplexChild::class, mappedBy = "complex", cascade = {"persist"}) */
protected Collection $complexChildren;

public function __construct()
{
$this->complexChildren = new ArrayCollection();
}

public function getType(): Suit
{
return $this->type;
}

public function setType(Suit $type): void
{
$this->type = $type;
}

public function getNumber(): int
{
return $this->number;
}

public function setNumber(int $number): void
{
$this->number = $number;
}

public function getComplexChildren(): Collection
{
return $this->complexChildren;
}

public function addComplexChild(ComplexChild $complexChild): void
{
$this->complexChildren->add($complexChild);
}
}
95 changes: 95 additions & 0 deletions tests/Doctrine/Tests/Models/GH10132/ComplexChild.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\GH10132;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\JoinColumns;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\Tests\Models\Enums\Suit;

/** @Entity */
class ComplexChild
{
/**
* @ManyToOne(targetEntity = Complex::class, inversedBy = "complexChildren")
* @JoinColumns(
* @JoinColumn(name = "complexType", referencedColumnName = "type", nullable = false),
* @JoinColumn(name = "complexNumber", referencedColumnName = "number", nullable = false)
* )
*/
protected Complex $complex;

/**
* @Id
* @Column(type = "string", enumType = Suit::class)
*/
protected Suit $complexType;

/**
* @Id
* @Column(type = "integer")
*/
protected int $complexNumber;

/**
* @Id
* @Column(type = "integer")
*/
protected int $point;

/** @OneToMany(targetEntity = SubComplexChild::class, mappedBy = "childComplex", cascade = {"persist", "remove"}) */
protected Collection $subComplexChildren;

public function setComplex(Complex $complex): void
{
$this->subComplexChildren = new ArrayCollection();

$complex->addComplexChild($this);
$this->complexType = $complex->getType();
$this->complexNumber = $complex->getNumber();
$this->complex = $complex;
}

public function getSuit(): Suit
{
return $this->complexType;
}

public function getComplexNumber(): int
{
return $this->complexNumber;
}

public function getComplex(): Complex
{
return $this->complex;
}

public function setPoint(int $point): void
{
$this->point = $point;
}

public function getPoint(): int
{
return $this->point;
}

public function getSubComplexChildren(): Collection
{
return $this->subComplexChildren;
}

public function addSubComplexChild(SubComplexChild $subComplexChild): void
{
$this->subComplexChildren[] = $subComplexChild;
}
}
75 changes: 75 additions & 0 deletions tests/Doctrine/Tests/Models/GH10132/SubComplexChild.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\GH10132;

use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\JoinColumns;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\Tests\Models\Enums\Suit;

/** @Entity */
class SubComplexChild
{
/**
* @ManyToOne(targetEntity = ComplexChild::class, inversedBy = "complexChildren")
* @JoinColumns(
* @JoinColumn(name = "complexType", referencedColumnName = "complexType", nullable = false),
* @JoinColumn(name = "complexNumber", referencedColumnName = "complexNumber", nullable = false),
* @JoinColumn(name = "complexChildPoint", referencedColumnName = "point", nullable = false)
* )
*/
protected ComplexChild $complexChild;

/**
* @Id
* @Column(type = "string", enumType = Suit::class)
*/
protected Suit $complexType;

/**
* @Id
* @Column(type = "integer")
*/
protected int $complexNumber;

/**
* @Id
* @Column(type = "integer")
*/
protected int $complexChildPoint;

/**
* @Id
* @Column(type = "integer")
*/
protected int $number;

public function getComplexChild(): ComplexChild
{
return $this->complexChild;
}

public function setComplexChild(ComplexChild $complexChild): void
{
$complexChild->addSubComplexChild($this);
$this->complexType = $complexChild->getSuit();
$this->complexNumber = $complexChild->getComplexNumber();
$this->complexChildPoint = $complexChild->getPoint();
$this->complexChild = $complexChild;
}

public function getNumber(): int
{
return $this->number;
}

public function setNumber(int $number): void
{
$this->number = $number;
}
}
74 changes: 74 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/GH10132Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\Tests\Models\Enums\Suit;
use Doctrine\Tests\Models\GH10132\Complex;
use Doctrine\Tests\Models\GH10132\ComplexChild;
use Doctrine\Tests\Models\GH10132\SubComplexChild;
use Doctrine\Tests\OrmFunctionalTestCase;

/**
* @requires PHP 8.1
*/
class GH10132Test extends OrmFunctionalTestCase
{
public function setUp(): void
{
parent::setUp();

$this->createSchemaForModels(
Complex::class,
ComplexChild::class,
SubComplexChild::class
);
}

public function testQueryBackedEnumInCompositeKeyJoin(): void
{
$complex = new Complex();
$complex->setType(Suit::Clubs);
$complex->setNumber(1);

$complexChild = new ComplexChild();
$complexChild->setComplex($complex);
$complexChild->setPoint(1);

$subComplexChild1 = new SubComplexChild();
$subComplexChild1->setComplexChild($complexChild);
$subComplexChild1->setNumber(1);

$subComplexChild2 = new SubComplexChild();
$subComplexChild2->setComplexChild($complexChild);
$subComplexChild2->setNumber(2);

$subComplexChild3 = new SubComplexChild();
$subComplexChild3->setComplexChild($complexChild);
$subComplexChild3->setNumber(3);

$this->_em->persist($complex);
$this->_em->persist($complexChild);
$this->_em->persist($subComplexChild1);
$this->_em->persist($subComplexChild2);
$this->_em->persist($subComplexChild3);
$this->_em->flush();
$this->_em->clear();

$qb = $this->_em->createQueryBuilder();
$qb->select('s')
->from(SubComplexChild::class, 's')
->where('s.complexType = :complexType')
->andWhere('s.complexNumber = :complexNumber')
->andWhere('s.complexChildPoint = :complexChildPoint')
->andWhere('s.number = :number');

$qb->setParameter('complexType', Suit::Clubs);
$qb->setParameter('complexNumber', 1);
$qb->setParameter('complexChildPoint', 1);
$qb->setParameter('number', 2);

self::assertNotNull($qb->getQuery()->getOneOrNullResult());
}
}

0 comments on commit cf726a3

Please sign in to comment.