Skip to content

Commit

Permalink
Fix association mapping with enum fields
Browse files Browse the repository at this point in the history
Enum fields as ID have worked for some time, but referencing these fields from other entities in association mappings such as OneToOne, ManyToOne and ManyToMany resulted in fatal error as there was an attempt to convert enum value to string improperly.
  • Loading branch information
michnovka committed Dec 7, 2022
1 parent aeed977 commit d5a6b36
Show file tree
Hide file tree
Showing 4 changed files with 149 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
51 changes: 51 additions & 0 deletions tests/Doctrine/Tests/Models/GH10132/Complex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?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;

/** @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 getComplexChildren(): Collection
{
return $this->complexChildren;
}

public function addComplexChild(ComplexChild $complexChild): void
{
$this->complexChildren->add($complexChild);
}
}
45 changes: 45 additions & 0 deletions tests/Doctrine/Tests/Models/GH10132/ComplexChild.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?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\ManyToOne;
use Doctrine\Tests\Models\Enums\Suit;

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

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

public function setComplex(Complex $complex): void
{
$complex->addComplexChild($this);
$this->complexType = $complex->getType();
$this->complex = $complex;
}

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

public function getComplex(): Complex
{
return $this->complex;
}
}
49 changes: 49 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/GH10132Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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\OrmFunctionalTestCase;

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

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

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

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

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

$qb = $this->_em->createQueryBuilder();
$qb->select('s')
->from(ComplexChild::class, 's')
->where('s.complexType = :complexType');

$qb->setParameter('complexType', Suit::Clubs);

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

0 comments on commit d5a6b36

Please sign in to comment.