Skip to content

Commit d355c4a

Browse files
authored
Merge pull request #12081 from doctrine/3.5.x
Merge 3.5.x up into 3.6.x
2 parents a1fdc6e + 62ca842 commit d355c4a

File tree

8 files changed

+125
-42
lines changed

8 files changed

+125
-42
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: "Continuous Integration"
1+
name: "CI"
22

33
on:
44
pull_request:

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
| [4.0.x][4.0] | [3.6.x][3.6] | [3.5.x][3.5] | [2.21.x][2.21] | [2.20.x][2.20] |
22
|:------------------------------------------------------:|:------------------------------------------------------:|:------------------------------------------------------:|:--------------------------------------------------------:|:--------------------------------------------------------:|
3-
| [![Build status][4.0 image]][4.0] | [![Build status][3.6 image]][3.6] | [![Build status][3.5 image]][3.5] | [![Build status][2.21 image]][2.21] | [![Build status][2.20 image]][2.20] |
3+
| [![Build status][4.0 image]][4.0 workflow] | [![Build status][3.6 image]][3.6 workflow] | [![Build status][3.5 image]][3.5 workflow] | [![Build status][2.21 image]][2.21 workflow] | [![Build status][2.20 image]][2.20 workflow] |
44
| [![Coverage Status][4.0 coverage image]][4.0 coverage] | [![Coverage Status][3.6 coverage image]][3.6 coverage] | [![Coverage Status][3.5 coverage image]][3.5 coverage] | [![Coverage Status][2.21 coverage image]][2.21 coverage] | [![Coverage Status][2.20 coverage image]][2.20 coverage] |
55

66
Doctrine ORM is an object-relational mapper for PHP 8.1+ that provides transparent persistence
@@ -18,21 +18,26 @@ without requiring unnecessary code duplication.
1818

1919
[4.0 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0.x
2020
[4.0]: https://github.com/doctrine/orm/tree/4.0.x
21+
[4.0 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A4.0.x
2122
[4.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/4.0.x/graph/badge.svg
2223
[4.0 coverage]: https://codecov.io/gh/doctrine/orm/branch/4.0.x
2324
[3.6 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.6.x
2425
[3.6]: https://github.com/doctrine/orm/tree/3.6.x
26+
[3.6 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A3.6.x
2527
[3.6 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.6.x/graph/badge.svg
2628
[3.6 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.6.x
2729
[3.5 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.5.x
2830
[3.5]: https://github.com/doctrine/orm/tree/3.5.x
31+
[3.5 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A3.5.x
2932
[3.5 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.5.x/graph/badge.svg
3033
[3.5 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.5.x
3134
[2.21 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.21.x
3235
[2.21]: https://github.com/doctrine/orm/tree/2.21.x
36+
[2.21 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A2.21.x
3337
[2.21 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.21.x/graph/badge.svg
3438
[2.21 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.21.x
3539
[2.20 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.20.x
3640
[2.20]: https://github.com/doctrine/orm/tree/2.20.x
41+
[2.20 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A2.20.x
3742
[2.20 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.20.x/graph/badge.svg
3843
[2.20 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.20.x

docs/en/cookbook/mysql-enums.rst

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,18 @@ entities:
4646
#[Entity]
4747
class Article
4848
{
49-
const STATUS_VISIBLE = 'visible';
50-
const STATUS_INVISIBLE = 'invisible';
49+
public const STATUS_VISIBLE = 'visible';
50+
public const STATUS_INVISIBLE = 'invisible';
5151
5252
#[Column(type: "string")]
5353
private $status;
5454
55-
public function setStatus($status)
55+
public function setStatus(string $status): void
5656
{
57-
if (!in_array($status, array(self::STATUS_VISIBLE, self::STATUS_INVISIBLE))) {
57+
if (!in_array($status, [self::STATUS_VISIBLE, self::STATUS_INVISIBLE], true)) {
5858
throw new \InvalidArgumentException("Invalid status");
5959
}
60+
6061
$this->status = $status;
6162
}
6263
}
@@ -92,37 +93,33 @@ For example for the previous enum type:
9293
9394
class EnumVisibilityType extends Type
9495
{
95-
const ENUM_VISIBILITY = 'enumvisibility';
96-
const STATUS_VISIBLE = 'visible';
97-
const STATUS_INVISIBLE = 'invisible';
96+
private const ENUM_VISIBILITY = 'enumvisibility';
97+
private const STATUS_VISIBLE = 'visible';
98+
private const STATUS_INVISIBLE = 'invisible';
9899
99-
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
100+
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
100101
{
101102
return "ENUM('visible', 'invisible')";
102103
}
103104
104-
public function convertToPHPValue($value, AbstractPlatform $platform)
105+
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed
105106
{
106107
return $value;
107108
}
108109
109-
public function convertToDatabaseValue($value, AbstractPlatform $platform)
110+
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): string
110111
{
111-
if (!in_array($value, array(self::STATUS_VISIBLE, self::STATUS_INVISIBLE))) {
112+
if (!in_array($value, [self::STATUS_VISIBLE, self::STATUS_INVISIBLE], true)) {
112113
throw new \InvalidArgumentException("Invalid status");
113114
}
115+
114116
return $value;
115117
}
116118
117-
public function getName()
119+
public function getName(): string
118120
{
119121
return self::ENUM_VISIBILITY;
120122
}
121-
122-
public function requiresSQLCommentHint(AbstractPlatform $platform)
123-
{
124-
return true;
125-
}
126123
}
127124
128125
You can register this type with ``Type::addType('enumvisibility', 'MyProject\DBAL\EnumVisibilityType');``.
@@ -151,37 +148,33 @@ You can generalize this approach easily to create a base class for enums:
151148
abstract class EnumType extends Type
152149
{
153150
protected $name;
154-
protected $values = array();
151+
protected $values = [];
155152
156-
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
153+
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
157154
{
158-
$values = array_map(function($val) { return "'".$val."'"; }, $this->values);
155+
$values = array_map(fn($val) => "'".$val."'", $this->values);
159156
160157
return "ENUM(".implode(", ", $values).")";
161158
}
162159
163-
public function convertToPHPValue($value, AbstractPlatform $platform)
160+
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed
164161
{
165162
return $value;
166163
}
167164
168-
public function convertToDatabaseValue($value, AbstractPlatform $platform)
165+
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed
169166
{
170-
if (!in_array($value, $this->values)) {
167+
if (!in_array($value, $this->values, true)) {
171168
throw new \InvalidArgumentException("Invalid '".$this->name."' value.");
172169
}
170+
173171
return $value;
174172
}
175173
176-
public function getName()
174+
public function getName(): string
177175
{
178176
return $this->name;
179177
}
180-
181-
public function requiresSQLCommentHint(AbstractPlatform $platform)
182-
{
183-
return true;
184-
}
185178
}
186179
187180
With this base class you can define an enum as easily as:
@@ -194,5 +187,5 @@ With this base class you can define an enum as easily as:
194187
class EnumVisibilityType extends EnumType
195188
{
196189
protected $name = 'enumvisibility';
197-
protected $values = array('visible', 'invisible');
190+
protected $values = ['visible', 'invisible'];
198191
}

src/Persisters/Entity/BasicEntityPersister.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -693,11 +693,11 @@ protected function prepareUpdateData(object $entity, bool $isInsert = false): ar
693693
$targetColumn = $joinColumn->referencedColumnName;
694694
$quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
695695

696-
$this->quotedColumns[$sourceColumn] = $quotedColumn;
697-
$this->columnTypes[$sourceColumn] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em);
698-
$result[$owningTable][$sourceColumn] = $newValId
699-
? $newValId[$targetClass->getFieldForColumn($targetColumn)]
700-
: null;
696+
$this->quotedColumns[$sourceColumn] = $quotedColumn;
697+
$this->columnTypes[$sourceColumn] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em);
698+
699+
$newValue = $newValId ? $newValId[$targetClass->getFieldForColumn($targetColumn)] : null;
700+
$result[$owningTable][$sourceColumn] = $newValue instanceof BackedEnum ? $newValue->value : $newValue;
701701
}
702702
}
703703

src/Tools/Console/Command/MappingDescribeCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ private function displayEntity(
115115
$this->formatField('Embedded class?', $metadata->isEmbeddedClass),
116116
$this->formatField('Parent classes', $metadata->parentClasses),
117117
$this->formatField('Sub classes', $metadata->subClasses),
118-
$this->formatField('Embedded classes', $metadata->subClasses),
118+
$this->formatField('Embedded classes', $metadata->embeddedClasses),
119119
$this->formatField('Identifier', $metadata->identifier),
120120
$this->formatField('Inheritance type', $metadata->inheritanceType),
121121
$this->formatField('Discriminator column', $metadata->discriminatorColumn),

src/Tools/SchemaValidator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public function validateClass(ClassMetadata $class): array
153153
$ce[] = 'The field ' . $class->name . '#' . $fieldName . ' is on the inverse side of a ' .
154154
'bi-directional relationship, but the specified mappedBy association on the target-entity ' .
155155
$assoc->targetEntity . '#' . $assoc->mappedBy . ' does not contain the required ' .
156-
"'inversedBy=\"" . $fieldName . "\"' attribute.";
156+
"'inversedBy: \"" . $fieldName . "\"' attribute.";
157157
} elseif ($targetMetadata->associationMappings[$assoc->mappedBy]->inversedBy !== $fieldName) {
158158
$ce[] = 'The mappings ' . $class->name . '#' . $fieldName . ' and ' .
159159
$assoc->targetEntity . '#' . $assoc->mappedBy . ' are ' .
@@ -174,7 +174,7 @@ public function validateClass(ClassMetadata $class): array
174174
$ce[] = 'The field ' . $class->name . '#' . $fieldName . ' is on the owning side of a ' .
175175
'bi-directional relationship, but the specified inversedBy association on the target-entity ' .
176176
$assoc->targetEntity . '#' . $assoc->inversedBy . ' does not contain the required ' .
177-
"'mappedBy=\"" . $fieldName . "\"' attribute.";
177+
"'mappedBy: \"" . $fieldName . "\"' attribute.";
178178
} elseif ($targetMetadata->associationMappings[$assoc->inversedBy]->mappedBy !== $fieldName) {
179179
$ce[] = 'The mappings ' . $class->name . '#' . $fieldName . ' and ' .
180180
$assoc->targetEntity . '#' . $assoc->inversedBy . ' are ' .
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional\Ticket;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
use Doctrine\ORM\Mapping\Column;
9+
use Doctrine\ORM\Mapping\Entity;
10+
use Doctrine\ORM\Mapping\GeneratedValue;
11+
use Doctrine\ORM\Mapping\Id;
12+
use Doctrine\Tests\OrmFunctionalTestCase;
13+
14+
class GH12063 extends OrmFunctionalTestCase
15+
{
16+
protected function setUp(): void
17+
{
18+
parent::setUp();
19+
20+
$this->createSchemaForModels(GH12063Association::class, GH12063Entity::class);
21+
}
22+
23+
public function testLoadedAssociationWithBackedEnum(): void
24+
{
25+
$association = new GH12063Association();
26+
$association->code = GH12063Code::One;
27+
28+
$this->_em->persist($association);
29+
$this->_em->flush();
30+
$this->_em->clear();
31+
32+
$entity = new GH12063Entity();
33+
$entity->association = $this->_em->find(GH12063Association::class, GH12063Code::One);
34+
35+
$this->_em->persist($entity);
36+
$this->_em->flush();
37+
38+
$this->assertNotNull($entity->id);
39+
}
40+
41+
public function testProxyAssociationWithBackedEnum(): void
42+
{
43+
$association = new GH12063Association();
44+
$association->code = GH12063Code::Two;
45+
46+
$this->_em->persist($association);
47+
$this->_em->flush();
48+
$this->_em->clear();
49+
50+
$entity = new GH12063Entity();
51+
$entity->association = $this->_em->getReference(GH12063Association::class, GH12063Code::Two);
52+
53+
$this->_em->persist($entity);
54+
$this->_em->flush();
55+
56+
$this->assertNotNull($entity->id);
57+
}
58+
}
59+
60+
enum GH12063Code: string
61+
{
62+
case One = 'one';
63+
case Two = 'two';
64+
}
65+
66+
#[Entity]
67+
class GH12063Association
68+
{
69+
#[Id]
70+
#[Column]
71+
public GH12063Code $code;
72+
}
73+
74+
#[Entity]
75+
class GH12063Entity
76+
{
77+
#[Id]
78+
#[Column]
79+
#[GeneratedValue]
80+
public int|null $id = null;
81+
82+
#[ORM\ManyToOne]
83+
#[ORM\JoinColumn(referencedColumnName: 'code')]
84+
public GH12063Association $association;
85+
}

tests/Tests/ORM/Tools/SchemaValidatorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public function testInvalidBiDirectionalRelationMappingMissingInversedByAttribut
135135
[
136136
'The field Doctrine\Tests\ORM\Tools\DDC3274One#two is on the inverse side of a bi-directional ' .
137137
'relationship, but the specified mappedBy association on the target-entity ' .
138-
"Doctrine\Tests\ORM\Tools\DDC3274Two#one does not contain the required 'inversedBy=\"two\"' attribute.",
138+
"Doctrine\Tests\ORM\Tools\DDC3274Two#one does not contain the required 'inversedBy: \"two\"' attribute.",
139139
],
140140
$ce,
141141
);
@@ -151,7 +151,7 @@ public function testInvalidBiDirectionalRelationMappingMissingMappedByAttribute(
151151
[
152152
'The field Doctrine\Tests\ORM\Tools\Issue9536Owner#one is on the owning side of a bi-directional ' .
153153
'relationship, but the specified inversedBy association on the target-entity ' .
154-
"Doctrine\Tests\ORM\Tools\Issue9536Target#two does not contain the required 'mappedBy=\"one\"' " .
154+
"Doctrine\Tests\ORM\Tools\Issue9536Target#two does not contain the required 'mappedBy: \"one\"' " .
155155
'attribute.',
156156
],
157157
$ce,

0 commit comments

Comments
 (0)