diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index b83ae43a889..a284dd38e2d 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -212,14 +212,14 @@
-
-
-
-
+
+
+
+
@@ -402,6 +402,7 @@
+
diff --git a/src/Mapping/ClassMetadata.php b/src/Mapping/ClassMetadata.php
index 70d3ea7042f..dea4006df3a 100644
--- a/src/Mapping/ClassMetadata.php
+++ b/src/Mapping/ClassMetadata.php
@@ -7,6 +7,8 @@
use BackedEnum;
use BadMethodCallException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
+use Doctrine\DBAL\Types\EnumType;
+use Doctrine\DBAL\Types\Types;
use Doctrine\Deprecations\Deprecation;
use Doctrine\Instantiator\Instantiator;
use Doctrine\Instantiator\InstantiatorInterface;
@@ -23,6 +25,7 @@
use ReflectionProperty;
use Stringable;
+use function array_column;
use function array_diff;
use function array_intersect;
use function array_key_exists;
@@ -1119,9 +1122,7 @@ private function validateAndCompleteTypedFieldMapping(array $mapping): array
{
$field = $this->reflClass->getProperty($mapping['fieldName']);
- $mapping = $this->typedFieldMapper->validateAndComplete($mapping, $field);
-
- return $mapping;
+ return $this->typedFieldMapper->validateAndComplete($mapping, $field);
}
/**
@@ -1232,6 +1233,10 @@ protected function validateAndCompleteFieldMapping(array $mapping): FieldMapping
if (! empty($mapping->id)) {
$this->containsEnumIdentifier = true;
}
+
+ if (class_exists(EnumType::class) && $mapping->type === Types::ENUM && ! isset($mapping->options['values'])) {
+ $mapping->options['values'] = array_column($mapping->enumType::cases(), 'value');
+ }
}
return $mapping;
diff --git a/src/Mapping/DefaultTypedFieldMapper.php b/src/Mapping/DefaultTypedFieldMapper.php
index 49144b8b7c8..4a6eb86d4e5 100644
--- a/src/Mapping/DefaultTypedFieldMapper.php
+++ b/src/Mapping/DefaultTypedFieldMapper.php
@@ -49,30 +49,37 @@ public function validateAndComplete(array $mapping, ReflectionProperty $field):
{
$type = $field->getType();
+ if (! $type instanceof ReflectionNamedType) {
+ return $mapping;
+ }
+
if (
- ! isset($mapping['type'])
- && ($type instanceof ReflectionNamedType)
+ ! $type->isBuiltin()
+ && enum_exists($type->getName())
+ && (! isset($mapping['type']) || $mapping['type'] === 'enum')
) {
- if (! $type->isBuiltin() && enum_exists($type->getName())) {
- $reflection = new ReflectionEnum($type->getName());
- if (! $reflection->isBacked()) {
- throw MappingException::backedEnumTypeRequired(
- $field->class,
- $mapping['fieldName'],
- $type->getName(),
- );
- }
+ $reflection = new ReflectionEnum($type->getName());
+ if (! $reflection->isBacked()) {
+ throw MappingException::backedEnumTypeRequired(
+ $field->class,
+ $mapping['fieldName'],
+ $type->getName(),
+ );
+ }
- assert(is_a($type->getName(), BackedEnum::class, true));
- $mapping['enumType'] = $type->getName();
- $type = $reflection->getBackingType();
+ assert(is_a($type->getName(), BackedEnum::class, true));
+ $mapping['enumType'] = $type->getName();
+ $type = $reflection->getBackingType();
- assert($type instanceof ReflectionNamedType);
- }
+ assert($type instanceof ReflectionNamedType);
+ }
- if (isset($this->typedFieldMappings[$type->getName()])) {
- $mapping['type'] = $this->typedFieldMappings[$type->getName()];
- }
+ if (isset($mapping['type'])) {
+ return $mapping;
+ }
+
+ if (isset($this->typedFieldMappings[$type->getName()])) {
+ $mapping['type'] = $this->typedFieldMappings[$type->getName()];
}
return $mapping;
diff --git a/tests/Tests/Models/Enums/CardNativeEnum.php b/tests/Tests/Models/Enums/CardNativeEnum.php
new file mode 100644
index 00000000000..8d06dba8e58
--- /dev/null
+++ b/tests/Tests/Models/Enums/CardNativeEnum.php
@@ -0,0 +1,25 @@
+ ['H', 'D', 'C', 'S']])]
+ public $suit;
+}
diff --git a/tests/Tests/Models/Enums/TypedCardNativeEnum.php b/tests/Tests/Models/Enums/TypedCardNativeEnum.php
new file mode 100644
index 00000000000..59e4eb00e55
--- /dev/null
+++ b/tests/Tests/Models/Enums/TypedCardNativeEnum.php
@@ -0,0 +1,23 @@
+_em->flush();
$this->_em->clear();
- $fetchedCard = $this->_em->find(Card::class, $card->id);
+ $fetchedCard = $this->_em->find($cardClass, $card->id);
$this->assertInstanceOf(Suit::class, $fetchedCard->suit);
$this->assertEquals(Suit::Clubs, $fetchedCard->suit);
@@ -447,13 +451,16 @@ public function testEnumWithNonMatchingDatabaseValueThrowsException(string $card
$this->_em->find($cardClass, $card->id);
}
- /** @return array */
- public static function provideCardClasses(): array
+ /** @return iterable */
+ public static function provideCardClasses(): iterable
{
- return [
- Card::class => [Card::class],
- TypedCard::class => [TypedCard::class],
- ];
+ yield Card::class => [Card::class];
+ yield TypedCard::class => [TypedCard::class];
+
+ if (class_exists(EnumType::class)) {
+ yield CardNativeEnum::class => [CardNativeEnum::class];
+ yield TypedCardNativeEnum::class => [TypedCardNativeEnum::class];
+ }
}
public function testItAllowsReadingAttributes(): void