Skip to content

Commit 8c0994f

Browse files
authored
Detect DBAL's number type (#11781)
1 parent 16f1be7 commit 8c0994f

File tree

4 files changed

+41
-19
lines changed

4 files changed

+41
-19
lines changed

src/Mapping/DefaultTypedFieldMapper.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Doctrine\ORM\Mapping;
66

77
use BackedEnum;
8+
use BcMath\Number;
89
use DateInterval;
910
use DateTime;
1011
use DateTimeImmutable;
@@ -40,7 +41,12 @@ final class DefaultTypedFieldMapper implements TypedFieldMapper
4041
/** @param array<class-string|ScalarName, class-string<Type>|string> $typedFieldMappings */
4142
public function __construct(array $typedFieldMappings = [])
4243
{
43-
$this->typedFieldMappings = array_merge(self::DEFAULT_TYPED_FIELD_MAPPINGS, $typedFieldMappings);
44+
$defaultMappings = self::DEFAULT_TYPED_FIELD_MAPPINGS;
45+
if (defined(Types::class . '::NUMBER')) { // DBAL 4.3+
46+
$defaultMappings[Number::class] = Types::NUMBER;
47+
}
48+
49+
$this->typedFieldMappings = array_merge($defaultMappings, $typedFieldMappings);
4450
}
4551

4652
/**

tests/Tests/Models/TypedProperties/UserTyped.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Doctrine\Tests\Models\TypedProperties;
66

7+
use BcMath\Number;
78
use DateInterval;
89
use DateTime;
910
use DateTimeImmutable;
@@ -54,6 +55,9 @@ class UserTyped
5455
#[ORM\Embedded]
5556
public Contact|null $contact = null;
5657

58+
#[ORM\Column(precision: 5, scale: 2)]
59+
public Number|null $bodyHeight = null;
60+
5761
public static function loadMetadata(ClassMetadata $metadata): void
5862
{
5963
$metadata->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_NONE);

tests/Tests/ORM/Mapping/ClassMetadataTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
use function assert;
6161
use function class_exists;
6262
use function count;
63+
use function defined;
6364
use function serialize;
6465
use function str_contains;
6566
use function str_replace;
@@ -199,6 +200,12 @@ public function testFieldTypeFromReflection(): void
199200
// float
200201
$cm->mapField(['fieldName' => 'float']);
201202
self::assertEquals('float', $cm->getTypeOfField('float'));
203+
204+
// number, requires DBAL 4.3+
205+
if (defined(Types::class . '::NUMBER')) {
206+
$cm->mapField(['fieldName' => 'bodyHeight']);
207+
self::assertEquals('number', $cm->getTypeOfField('bodyHeight'));
208+
}
202209
}
203210

204211
#[TestGroup('GH10313')]

tests/Tests/ORM/Mapping/TypedFieldMapperTest.php

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
use Doctrine\Tests\Models\TypedProperties\UserTyped;
1212
use Doctrine\Tests\ORM\Mapping\TypedFieldMapper\CustomIntAsStringTypedFieldMapper;
1313
use Doctrine\Tests\OrmTestCase;
14+
use Generator;
1415
use PHPUnit\Framework\Attributes\DataProvider;
1516
use PHPUnit\Framework\Attributes\Group;
1617
use ReflectionClass;
1718

19+
use function defined;
20+
1821
#[Group('GH10313')]
1922
class TypedFieldMapperTest extends OrmTestCase
2023
{
@@ -36,36 +39,38 @@ private static function chainTypedFieldMapper(): ChainTypedFieldMapper
3639
/**
3740
* Data Provider for NamingStrategy#classToTableName
3841
*
39-
* @return array<
42+
* @return Generator<
4043
* array{
4144
* TypedFieldMapper,
4245
* ReflectionClass,
4346
* array{fieldName: string, enumType?: string, type?: mixed},
4447
* array{fieldName: string, enumType?: string, type?: mixed}
4548
* }>
4649
*/
47-
public static function dataFieldToMappedField(): array
50+
public static function dataFieldToMappedField(): Generator
4851
{
4952
$reflectionClass = new ReflectionClass(UserTyped::class);
5053

51-
return [
52-
// DefaultTypedFieldMapper
53-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'id'], ['fieldName' => 'id', 'type' => Types::INTEGER]],
54-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'username'], ['fieldName' => 'username', 'type' => Types::STRING]],
55-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'dateInterval'], ['fieldName' => 'dateInterval', 'type' => Types::DATEINTERVAL]],
56-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'dateTime'], ['fieldName' => 'dateTime', 'type' => Types::DATETIME_MUTABLE]],
57-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'dateTimeImmutable'], ['fieldName' => 'dateTimeImmutable', 'type' => Types::DATETIME_IMMUTABLE]],
58-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'array'], ['fieldName' => 'array', 'type' => Types::JSON]],
59-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'boolean'], ['fieldName' => 'boolean', 'type' => Types::BOOLEAN]],
60-
[self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'float'], ['fieldName' => 'float', 'type' => Types::FLOAT]],
54+
// DefaultTypedFieldMapper
55+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'id'], ['fieldName' => 'id', 'type' => Types::INTEGER]];
56+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'username'], ['fieldName' => 'username', 'type' => Types::STRING]];
57+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'dateInterval'], ['fieldName' => 'dateInterval', 'type' => Types::DATEINTERVAL]];
58+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'dateTime'], ['fieldName' => 'dateTime', 'type' => Types::DATETIME_MUTABLE]];
59+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'dateTimeImmutable'], ['fieldName' => 'dateTimeImmutable', 'type' => Types::DATETIME_IMMUTABLE]];
60+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'array'], ['fieldName' => 'array', 'type' => Types::JSON]];
61+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'boolean'], ['fieldName' => 'boolean', 'type' => Types::BOOLEAN]];
62+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'float'], ['fieldName' => 'float', 'type' => Types::FLOAT]];
63+
64+
if (defined(Types::class . '::NUMBER')) {
65+
yield [self::defaultTypedFieldMapper(), $reflectionClass, ['fieldName' => 'bodyHeight'], ['fieldName' => 'bodyHeight', 'type' => Types::NUMBER]];
66+
}
6167

62-
// CustomIntAsStringTypedFieldMapper
63-
[self::customTypedFieldMapper(), $reflectionClass, ['fieldName' => 'id'], ['fieldName' => 'id', 'type' => Types::STRING]],
68+
// CustomIntAsStringTypedFieldMapper
69+
yield [self::customTypedFieldMapper(), $reflectionClass, ['fieldName' => 'id'], ['fieldName' => 'id', 'type' => Types::STRING]];
6470

65-
// ChainTypedFieldMapper
66-
[self::chainTypedFieldMapper(), $reflectionClass, ['fieldName' => 'id'], ['fieldName' => 'id', 'type' => Types::STRING]],
67-
[self::chainTypedFieldMapper(), $reflectionClass, ['fieldName' => 'username'], ['fieldName' => 'username', 'type' => Types::STRING]],
68-
];
71+
// ChainTypedFieldMapper
72+
yield [self::chainTypedFieldMapper(), $reflectionClass, ['fieldName' => 'id'], ['fieldName' => 'id', 'type' => Types::STRING]];
73+
yield [self::chainTypedFieldMapper(), $reflectionClass, ['fieldName' => 'username'], ['fieldName' => 'username', 'type' => Types::STRING]];
6974
}
7075

7176
/**

0 commit comments

Comments
 (0)