diff --git a/src/Tools/SchemaValidator.php b/src/Tools/SchemaValidator.php index 6ebe991876c..7b4e6176a41 100644 --- a/src/Tools/SchemaValidator.php +++ b/src/Tools/SchemaValidator.php @@ -39,6 +39,7 @@ use function in_array; use function interface_exists; use function is_a; +use function method_exists; use function sprintf; /** @@ -49,9 +50,9 @@ class SchemaValidator { /** - * It maps built-in Doctrine types to PHP types + * Map built-in Doctrine DBAL 3 types to PHP types */ - private const BUILTIN_TYPES_MAP = [ + private const BUILTIN_TYPES_MAP_DBAL3 = [ AsciiStringType::class => 'string', BigIntType::class => 'string', BooleanType::class => 'bool', @@ -66,6 +67,24 @@ class SchemaValidator TextType::class => 'string', ]; + /** + * Map built-in Doctrine DBAL 4+ types to PHP types + */ + private const BUILTIN_TYPES_MAP = [ + AsciiStringType::class => 'string', + BigIntType::class => 'string|int', + BooleanType::class => 'bool', + DecimalType::class => 'string', + FloatType::class => 'float', + GuidType::class => 'string', + IntegerType::class => 'int', + JsonType::class => 'array', + SimpleArrayType::class => 'array', + SmallIntType::class => 'int', + StringType::class => 'string', + TextType::class => 'string', + ]; + public function __construct( private readonly EntityManagerInterface $em, private readonly bool $validatePropertyTypes = true, @@ -436,6 +455,10 @@ private function findBuiltInType(Type $type): string|null { $typeName = $type::class; - return self::BUILTIN_TYPES_MAP[$typeName] ?? null; + if (method_exists(BigIntType::class, 'getName')) { // DBAL 3 + return self::BUILTIN_TYPES_MAP_DBAL3[$typeName] ?? null; + } else { // DBAL 4+ + return self::BUILTIN_TYPES_MAP[$typeName] ?? null; + } } } diff --git a/tests/Tests/ORM/Tools/SchemaValidatorTest.php b/tests/Tests/ORM/Tools/SchemaValidatorTest.php index b7141b0d99d..a153e4e77b6 100644 --- a/tests/Tests/ORM/Tools/SchemaValidatorTest.php +++ b/tests/Tests/ORM/Tools/SchemaValidatorTest.php @@ -6,6 +6,8 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\DBAL\Types\BigIntType; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\DiscriminatorMap; @@ -30,6 +32,8 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; +use function method_exists; + class SchemaValidatorTest extends OrmTestCase { private EntityManagerInterface|null $em = null; @@ -228,6 +232,47 @@ public function testInvalidAssociationTowardsMappedSuperclass(): void $ce, ); } + + public function testBigintMappedToStringInt(): void + { + $class = $this->em->getClassMetadata(BigintMappedToStringInt::class); + $ce = $this->validator->validateClass($class); + + $this->assertEquals([], $ce); // Same for DBAL 3 and 4+ + } + + public function testBigintMappedToInt(): void + { + $class = $this->em->getClassMetadata(BigintMappedToInt::class); + $ce = $this->validator->validateClass($class); + + if (method_exists(BigIntType::class, 'getName')) { // DBAL 3 + $this->assertEquals( + ["The field 'Doctrine\Tests\ORM\Tools\BigintMappedToInt#bigint' has the property type 'int' that differs from the metadata field type 'string' returned by the 'bigint' DBAL type."], + $ce, + ); + } else { // DBAL 4+ + $this->assertEquals( + ["The field 'Doctrine\Tests\ORM\Tools\BigintMappedToInt#bigint' has the property type 'int' that differs from the metadata field type 'string|int' returned by the 'bigint' DBAL type."], + $ce, + ); + } + } + + public function testBigintMappedToString(): void + { + $class = $this->em->getClassMetadata(BigintMappedToString::class); + $ce = $this->validator->validateClass($class); + + if (method_exists(BigIntType::class, 'getName')) { // DBAL 3 + $this->assertEquals([], $ce); + } else { // DBAL 4+ + $this->assertEquals( + ["The field 'Doctrine\Tests\ORM\Tools\BigintMappedToString#bigint' has the property type 'string' that differs from the metadata field type 'string|int' returned by the 'bigint' DBAL type."], + $ce, + ); + } + } } #[MappedSuperclass] @@ -547,3 +592,39 @@ class InvalidMappedSuperClass #[ManyToMany(targetEntity: 'InvalidMappedSuperClass', mappedBy: 'invalid')] private $selfWhatever; } + +#[Entity] +class BigintMappedToStringInt +{ + #[Id] + #[Column] + #[GeneratedValue] + private int $id; + + #[Column(type: Types::BIGINT)] + private string|int $bigint; +} + +#[Entity] +class BigintMappedToInt +{ + #[Id] + #[Column] + #[GeneratedValue] + private int $id; + + #[Column(type: Types::BIGINT)] + private int $bigint; +} + +#[Entity] +class BigintMappedToString +{ + #[Id] + #[Column] + #[GeneratedValue] + private int $id; + + #[Column(type: Types::BIGINT)] + private string $bigint; +}