Skip to content

Commit 24ce351

Browse files
committed
EntityRelationRule - fix composite keys
1 parent e745610 commit 24ce351

File tree

6 files changed

+67
-6
lines changed

6 files changed

+67
-6
lines changed

src/Rules/Doctrine/ORM/EntityColumnRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ public function processNode(Node $node, Scope $scope): array
103103
)] : [];
104104
}
105105

106-
$identifier = null;
106+
$identifiers = [];
107107
if ($metadata->generatorType !== 5) { // ClassMetadataInfo::GENERATOR_TYPE_NONE
108108
try {
109-
$identifier = $metadata->getSingleIdentifierFieldName();
109+
$identifiers = $metadata->getIdentifierFieldNames();
110110
} catch (Throwable $e) {
111111
$mappingException = 'Doctrine\ORM\Mapping\MappingException';
112112
if (!$e instanceof $mappingException) {
@@ -148,7 +148,7 @@ public function processNode(Node $node, Scope $scope): array
148148
);
149149
}
150150
$propertyReadableType = TypeTraverser::map($property->getReadableType(), $transformArrays);
151-
if (!$writableToDatabaseType->isSuperTypeOf($identifier === $propertyName && !$nullable ? TypeCombinator::removeNull($propertyReadableType) : $propertyReadableType)->yes()) {
151+
if (!$writableToDatabaseType->isSuperTypeOf(in_array($propertyName, $identifiers, true) && !$nullable ? TypeCombinator::removeNull($propertyReadableType) : $propertyReadableType)->yes()) {
152152
$errors[] = sprintf(
153153
'Property %s::$%s type mapping mismatch: property can contain %s but database expects %s.',
154154
$className,

src/Rules/Doctrine/ORM/EntityRelationRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ public function processNode(Node $node, Scope $scope): array
7474
return [];
7575
}
7676
$associationMapping = $metadata->associationMappings[$propertyName];
77-
$identifier = null;
77+
$identifiers = [];
7878
try {
79-
$identifier = $metadata->getSingleIdentifierFieldName();
79+
$identifiers = $metadata->getIdentifierFieldNames();
8080
} catch (\Throwable $e) {
8181
$mappingException = 'Doctrine\ORM\Mapping\MappingException';
8282
if (!$e instanceof $mappingException) {
@@ -88,7 +88,7 @@ public function processNode(Node $node, Scope $scope): array
8888
$toMany = false;
8989
if ((bool) ($associationMapping['type'] & 3)) { // ClassMetadataInfo::TO_ONE
9090
$columnType = new ObjectType($associationMapping['targetEntity']);
91-
if ($identifier !== null && $identifier === $propertyName) {
91+
if (in_array($propertyName, $identifiers, true)) {
9292
$nullable = false;
9393
} else {
9494
$nullable = $associationMapping['joinColumns'][0]['nullable'] ?? true;

tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ public function generatedIdsProvider(): Iterator
136136
];
137137
yield 'nullable property' => [__DIR__ . '/data/GeneratedIdEntity3.php', []];
138138
yield 'nullable both' => [__DIR__ . '/data/GeneratedIdEntity4.php', []];
139+
yield 'composite' => [__DIR__ . '/data/CompositePrimaryKeyEntity1.php', []];
139140
}
140141

141142
public function testCustomType(): void

tests/Rules/Doctrine/ORM/EntityRelationRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ public function ruleProvider(): Iterator
147147
],
148148
],
149149
];
150+
151+
yield 'composite primary key' => [
152+
__DIR__ . '/data/CompositePrimaryKeyEntity2.php',
153+
[],
154+
];
150155
}
151156

152157
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Doctrine\ORM;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
class CompositePrimaryKeyEntity1
11+
{
12+
13+
/**
14+
* @ORM\Id()
15+
* @ORM\GeneratedValue()
16+
* @ORM\Column(type="bigint", nullable=true)
17+
* @var string
18+
*/
19+
private $id;
20+
21+
/**
22+
* @ORM\Id()
23+
* @ORM\Column(type="string")
24+
* @var string|null
25+
*/
26+
private $country;
27+
28+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Doctrine\ORM;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
class CompositePrimaryKeyEntity2
11+
{
12+
13+
/**
14+
* @ORM\Id()
15+
* @ORM\ManyToOne(targetEntity="PHPStan\Rules\Doctrine\ORM\EntityWithRelations", inversedBy="countries")
16+
* @var EntityWithRelations
17+
*/
18+
private $post;
19+
20+
/**
21+
* @ORM\Id()
22+
* @ORM\Column(type="string")
23+
* @var string
24+
*/
25+
private $country;
26+
27+
}

0 commit comments

Comments
 (0)