Skip to content

Commit 9e4f8d2

Browse files
committed
Failing test: Duplicate private fields not detected
This test case demonstrates a situation where two entities inherit from each other. Both entity classes have a private property named `field`. (Inheritance is set up correctly, but that is irrelevant here.) Technically, that's two properties on two separate classes. Also, the mapping configuration given suggests to put both properties into separate database columns. I think this violates fundamental design assumptions, since `ClassMetadata::$fieldMappings` is indexed by "field name" – there is no room for juggling with duplicate private fields being declared in different classes. My guess is this is a design limitation that would be very hard to change, should be documented as a limitation and be rejected when it is noticed. The same applies to association mappings and embeddables. The current situation, however, is that the property and mapping configuration will be picked up from the first (parent) entity class. At least the annotation and attribute mapping driver will then silently skip the property on the subclass (see doctrine#10417). Mapping configuration for `GH10450ChildClass::$field` will never be considered. This property will (silently) remain unmapped.
1 parent feda210 commit 9e4f8d2

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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\MappingException;
9+
use Doctrine\Tests\OrmTestCase;
10+
use Generator;
11+
12+
class GH10450Test extends OrmTestCase
13+
{
14+
/**
15+
* @param class-string $className
16+
*
17+
* @dataProvider classesThatOverrideFieldNames
18+
*/
19+
public function testDuplicatePrivateFieldsShallBeRejected(string $className): void
20+
{
21+
$em = $this->getTestEntityManager();
22+
23+
$this->expectException(MappingException::class);
24+
25+
$em->getClassMetadata($className);
26+
}
27+
28+
public function classesThatOverrideFieldNames(): Generator
29+
{
30+
yield 'Entity class that redeclares a private field inherited from a base entity' => [GH10450EntityChild::class];
31+
yield 'Entity class that redeclares a private field inherited from a mapped superclass' => [GH10450MappedSuperclassChild::class];
32+
}
33+
}
34+
35+
/**
36+
* @ORM\Entity
37+
* @ORM\InheritanceType("JOINED")
38+
* @ORM\DiscriminatorMap({ "base": "GH10450BaseEntity", "child": "GH10450EntityChild" })
39+
* @ORM\DiscriminatorColumn(name="type")
40+
*/
41+
class GH10450BaseEntity
42+
{
43+
/**
44+
* @ORM\Column(type="integer")
45+
* @ORM\Id
46+
* @ORM\GeneratedValue
47+
*
48+
* @var int
49+
*/
50+
private $id;
51+
52+
/**
53+
* @ORM\Column(type="text", name="base")
54+
*
55+
* @var string
56+
*/
57+
private $field;
58+
}
59+
60+
/**
61+
* @ORM\Entity
62+
*/
63+
class GH10450EntityChild extends GH10450BaseEntity
64+
{
65+
/**
66+
* @ORM\Column(type="text", name="child")
67+
*
68+
* @var string
69+
*/
70+
private $field;
71+
}
72+
73+
/**
74+
* @ORM\MappedSuperclass
75+
*/
76+
class GH10450BaseMappedSuperclass
77+
{
78+
/**
79+
* @ORM\Column(type="integer")
80+
* @ORM\Id
81+
* @ORM\GeneratedValue
82+
*
83+
* @var int
84+
*/
85+
private $id;
86+
87+
/**
88+
* @ORM\Column(type="text", name="base")
89+
*
90+
* @var string
91+
*/
92+
private $field;
93+
}
94+
95+
/**
96+
* @ORM\Entity
97+
*/
98+
class GH10450MappedSuperclassChild extends GH10450BaseMappedSuperclass
99+
{
100+
/**
101+
* @ORM\Column(type="text", name="child")
102+
*
103+
* @var string
104+
*/
105+
private $field;
106+
}

0 commit comments

Comments
 (0)