Skip to content

Commit 3e18a58

Browse files
authored
Merge pull request #11907 from xabbuh/dbal-6728
do not use deprecated foreign key constraint features
2 parents d8cb71f + a9f9202 commit 3e18a58

File tree

5 files changed

+159
-22
lines changed

5 files changed

+159
-22
lines changed

phpstan-baseline.neon

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,30 @@ parameters:
13501350
count: 1
13511351
path: src/Mapping/Driver/AttributeDriver.php
13521352

1353+
-
1354+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedColumnNames\(\)\.$#'
1355+
identifier: method.notFound
1356+
count: 1
1357+
path: src/Mapping/Driver/DatabaseDriver.php
1358+
1359+
-
1360+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedTableName\(\)\.$#'
1361+
identifier: method.notFound
1362+
count: 1
1363+
path: src/Mapping/Driver/DatabaseDriver.php
1364+
1365+
-
1366+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencingColumnNames\(\)\.$#'
1367+
identifier: method.notFound
1368+
count: 1
1369+
path: src/Mapping/Driver/DatabaseDriver.php
1370+
1371+
-
1372+
message: '#^Call to method toString\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
1373+
identifier: class.notFound
1374+
count: 2
1375+
path: src/Mapping/Driver/DatabaseDriver.php
1376+
13531377
-
13541378
message: '#^Cannot call method getName\(\) on Doctrine\\DBAL\\Schema\\Column\|false\.$#'
13551379
identifier: method.nonObject
@@ -1398,6 +1422,12 @@ parameters:
13981422
count: 4
13991423
path: src/Mapping/Driver/DatabaseDriver.php
14001424

1425+
-
1426+
message: '#^Parameter \$name of anonymous function has invalid type Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
1427+
identifier: class.notFound
1428+
count: 2
1429+
path: src/Mapping/Driver/DatabaseDriver.php
1430+
14011431
-
14021432
message: '#^Method Doctrine\\ORM\\Mapping\\Driver\\SimplifiedXmlDriver\:\:__construct\(\) has parameter \$fileExtension with no type specified\.$#'
14031433
identifier: missingType.parameter
@@ -3048,12 +3078,42 @@ parameters:
30483078
count: 3
30493079
path: src/Tools/SchemaTool.php
30503080

3081+
-
3082+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedColumnNames\(\)\.$#'
3083+
identifier: method.notFound
3084+
count: 1
3085+
path: src/Tools/SchemaTool.php
3086+
3087+
-
3088+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedTableName\(\)\.$#'
3089+
identifier: method.notFound
3090+
count: 1
3091+
path: src/Tools/SchemaTool.php
3092+
3093+
-
3094+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencingColumnNames\(\)\.$#'
3095+
identifier: method.notFound
3096+
count: 1
3097+
path: src/Tools/SchemaTool.php
3098+
3099+
-
3100+
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\Table\:\:dropForeignKey\(\)\.$#'
3101+
identifier: method.notFound
3102+
count: 1
3103+
path: src/Tools/SchemaTool.php
3104+
30513105
-
30523106
message: '#^Call to function is_numeric\(\) with int\<0, max\> will always evaluate to true\.$#'
30533107
identifier: function.alreadyNarrowedType
30543108
count: 1
30553109
path: src/Tools/SchemaTool.php
30563110

3111+
-
3112+
message: '#^Call to method toString\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
3113+
identifier: class.notFound
3114+
count: 2
3115+
path: src/Tools/SchemaTool.php
3116+
30573117
-
30583118
message: '#^Method Doctrine\\ORM\\Tools\\SchemaTool\:\:addDiscriminatorColumnDefinition\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
30593119
identifier: missingType.generics
@@ -3156,6 +3216,12 @@ parameters:
31563216
count: 1
31573217
path: src/Tools/SchemaTool.php
31583218

3219+
-
3220+
message: '#^Parameter \$name of anonymous function has invalid type Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
3221+
identifier: class.notFound
3222+
count: 2
3223+
path: src/Tools/SchemaTool.php
3224+
31593225
-
31603226
message: '#^Property Doctrine\\ORM\\Tools\\SchemaTool\:\:\$schemaManager with generic class Doctrine\\DBAL\\Schema\\AbstractSchemaManager does not specify its types\: T$#'
31613227
identifier: missingType.generics

src/Mapping/Driver/DatabaseDriver.php

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
use Doctrine\DBAL\Schema\AbstractSchemaManager;
88
use Doctrine\DBAL\Schema\Column;
9+
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
10+
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
911
use Doctrine\DBAL\Schema\SchemaException;
1012
use Doctrine\DBAL\Schema\Table;
1113
use Doctrine\DBAL\Types\Type;
@@ -21,12 +23,14 @@
2123

2224
use function array_diff;
2325
use function array_keys;
26+
use function array_map;
2427
use function array_merge;
2528
use function assert;
2629
use function count;
2730
use function current;
2831
use function get_debug_type;
2932
use function in_array;
33+
use function method_exists;
3034
use function preg_replace;
3135
use function sort;
3236
use function sprintf;
@@ -187,7 +191,7 @@ public function loadMetadataForClass(string $className, PersistenceClassMetadata
187191
foreach ($this->manyToManyTables as $manyTable) {
188192
foreach ($manyTable->getForeignKeys() as $foreignKey) {
189193
// foreign key maps to the table of the current entity, many to many association probably exists
190-
if (! (strtolower($tableName) === strtolower($foreignKey->getForeignTableName()))) {
194+
if (! (strtolower($tableName) === strtolower(self::getReferencedTableName($foreignKey)))) {
191195
continue;
192196
}
193197

@@ -207,22 +211,22 @@ public function loadMetadataForClass(string $className, PersistenceClassMetadata
207211
continue;
208212
}
209213

210-
$localColumn = current($myFk->getLocalColumns());
214+
$localColumn = current(self::getReferencingColumnNames($myFk));
211215

212216
$associationMapping = [];
213-
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getLocalColumns()), true);
214-
$associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName());
217+
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($otherFk)), true);
218+
$associationMapping['targetEntity'] = $this->getClassNameForTable(self::getReferencedTableName($otherFk));
215219

216220
if (current($manyTable->getColumns())->getName() === $localColumn) {
217-
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getLocalColumns()), true);
221+
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($myFk)), true);
218222
$associationMapping['joinTable'] = [
219223
'name' => strtolower($manyTable->getName()),
220224
'joinColumns' => [],
221225
'inverseJoinColumns' => [],
222226
];
223227

224-
$fkCols = $myFk->getForeignColumns();
225-
$cols = $myFk->getLocalColumns();
228+
$fkCols = self::getReferencedColumnNames($myFk);
229+
$cols = self::getReferencingColumnNames($myFk);
226230

227231
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) {
228232
$associationMapping['joinTable']['joinColumns'][] = [
@@ -231,8 +235,8 @@ public function loadMetadataForClass(string $className, PersistenceClassMetadata
231235
];
232236
}
233237

234-
$fkCols = $otherFk->getForeignColumns();
235-
$cols = $otherFk->getLocalColumns();
238+
$fkCols = self::getReferencedColumnNames($otherFk);
239+
$cols = self::getReferencingColumnNames($otherFk);
236240

237241
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) {
238242
$associationMapping['joinTable']['inverseJoinColumns'][] = [
@@ -241,7 +245,7 @@ public function loadMetadataForClass(string $className, PersistenceClassMetadata
241245
];
242246
}
243247
} else {
244-
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getLocalColumns()), true);
248+
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($myFk)), true);
245249
}
246250

247251
$metadata->mapManyToMany($associationMapping);
@@ -267,7 +271,7 @@ private function reverseEngineerMappingFromDatabase(): void
267271
$allForeignKeyColumns = [];
268272

269273
foreach ($foreignKeys as $foreignKey) {
270-
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
274+
$allForeignKeyColumns = array_merge($allForeignKeyColumns, self::getReferencingColumnNames($foreignKey));
271275
}
272276

273277
$primaryKey = $table->getPrimaryKey();
@@ -331,7 +335,7 @@ private function buildFieldMappings(ClassMetadata $metadata): void
331335
$allForeignKeys = [];
332336

333337
foreach ($foreignKeys as $foreignKey) {
334-
$allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns());
338+
$allForeignKeys = array_merge($allForeignKeys, self::getReferencingColumnNames($foreignKey));
335339
}
336340

337341
$ids = [];
@@ -441,9 +445,9 @@ private function buildToOneAssociationMappings(ClassMetadata $metadata): void
441445
$foreignKeys = $this->tables[$tableName]->getForeignKeys();
442446

443447
foreach ($foreignKeys as $foreignKey) {
444-
$foreignTableName = $foreignKey->getForeignTableName();
445-
$fkColumns = $foreignKey->getLocalColumns();
446-
$fkForeignColumns = $foreignKey->getForeignColumns();
448+
$foreignTableName = self::getReferencedTableName($foreignKey);
449+
$fkColumns = self::getReferencingColumnNames($foreignKey);
450+
$fkForeignColumns = self::getReferencedColumnNames($foreignKey);
447451
$localColumn = current($fkColumns);
448452
$associationMapping = [
449453
'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true),
@@ -527,4 +531,33 @@ private function getFieldNameForColumn(
527531

528532
return $this->inflector->camelize($columnName);
529533
}
534+
535+
private static function getReferencedTableName(ForeignKeyConstraint $foreignKey): string
536+
{
537+
if (method_exists(ForeignKeyConstraint::class, 'getReferencedTableName')) {
538+
return $foreignKey->getReferencedTableName()->toString();
539+
}
540+
541+
return $foreignKey->getForeignTableName();
542+
}
543+
544+
/** @return string[] */
545+
private static function getReferencingColumnNames(ForeignKeyConstraint $foreignKey): array
546+
{
547+
if (method_exists(ForeignKeyConstraint::class, 'getReferencingColumnNames')) {
548+
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencingColumnNames());
549+
}
550+
551+
return $foreignKey->getLocalColumns();
552+
}
553+
554+
/** @return string[] */
555+
private static function getReferencedColumnNames(ForeignKeyConstraint $foreignKey): array
556+
{
557+
if (method_exists(ForeignKeyConstraint::class, 'getReferencedColumnNames')) {
558+
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencedColumnNames());
559+
}
560+
561+
return $foreignKey->getForeignColumns();
562+
}
530563
}

src/Tools/SchemaTool.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Doctrine\DBAL\Platforms\AbstractPlatform;
99
use Doctrine\DBAL\Schema\AbstractAsset;
1010
use Doctrine\DBAL\Schema\AbstractSchemaManager;
11+
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
1112
use Doctrine\DBAL\Schema\Index;
1213
use Doctrine\DBAL\Schema\Name\Identifier;
1314
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
@@ -34,6 +35,7 @@
3435
use function array_filter;
3536
use function array_flip;
3637
use function array_intersect_key;
38+
use function array_map;
3739
use function assert;
3840
use function class_exists;
3941
use function count;
@@ -729,7 +731,18 @@ private function gatherRelationJoinColumns(
729731
) {
730732
foreach ($theJoinTable->getForeignKeys() as $fkName => $key) {
731733
if (
732-
count(array_diff($key->getLocalColumns(), $localColumns)) === 0
734+
class_exists(ForeignKeyConstraintEditor::class)
735+
&& count(array_diff(array_map(static fn (UnqualifiedName $name) => $name->toString(), $key->getReferencingColumnNames()), $localColumns)) === 0
736+
&& (($key->getReferencedTableName()->toString() !== $foreignTableName)
737+
|| 0 < count(array_diff(array_map(static fn (UnqualifiedName $name) => $name->toString(), $key->getReferencedColumnNames()), $foreignColumns)))
738+
) {
739+
$theJoinTable->dropForeignKey($fkName);
740+
break;
741+
}
742+
743+
if (
744+
! class_exists(ForeignKeyConstraintEditor::class)
745+
&& count(array_diff($key->getLocalColumns(), $localColumns)) === 0
733746
&& (($key->getForeignTableName() !== $foreignTableName)
734747
|| 0 < count(array_diff($key->getForeignColumns(), $foreignColumns)))
735748
) {

tests/Tests/ORM/Functional/Ticket/DDC2138Test.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
use Doctrine\Common\Collections\ArrayCollection;
88
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
9+
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
10+
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
911
use Doctrine\DBAL\Schema\Table as DbalTable;
1012
use Doctrine\ORM\Mapping\Column;
1113
use Doctrine\ORM\Mapping\DiscriminatorColumn;
@@ -22,7 +24,9 @@
2224
use Doctrine\Tests\OrmFunctionalTestCase;
2325
use PHPUnit\Framework\Attributes\Group;
2426

27+
use function array_map;
2528
use function assert;
29+
use function class_exists;
2630
use function reset;
2731

2832
class DDC2138Test extends OrmFunctionalTestCase
@@ -49,9 +53,17 @@ public function testForeignKeyOnSTIWithMultipleMapping(): void
4953

5054
$fk = reset($foreignKeys);
5155
assert($fk instanceof ForeignKeyConstraint);
52-
self::assertEquals('users', $fk->getForeignTableName());
5356

54-
$localColumns = $fk->getLocalColumns();
57+
if (class_exists(ForeignKeyConstraintEditor::class)) {
58+
self::assertEquals('users', $fk->getReferencedTableName()->toString());
59+
60+
$localColumns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $fk->getReferencingColumnNames());
61+
} else {
62+
self::assertEquals('users', $fk->getForeignTableName());
63+
64+
$localColumns = $fk->getLocalColumns();
65+
}
66+
5567
self::assertContains('user_id', $localColumns);
5668
self::assertCount(1, $localColumns);
5769
}

tests/Tests/ORM/Tools/SchemaToolTest.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
namespace Doctrine\Tests\ORM\Tools;
66

77
use Doctrine\Common\Collections\Collection;
8+
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
9+
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
810
use Doctrine\DBAL\Schema\Table as DbalTable;
911
use Doctrine\ORM\Mapping\ClassMetadata;
1012
use Doctrine\ORM\Mapping\Column;
@@ -43,6 +45,8 @@
4345
use Doctrine\Tests\OrmTestCase;
4446
use PHPUnit\Framework\Attributes\Group;
4547

48+
use function array_map;
49+
use function class_exists;
4650
use function count;
4751
use function current;
4852

@@ -291,12 +295,21 @@ public function testDerivedCompositeKey(): void
291295
];
292296

293297
foreach ($childTableForeignKeys as $foreignKey) {
294-
self::assertArrayHasKey($foreignKey->getForeignTableName(), $expectedColumns);
298+
if (class_exists(ForeignKeyConstraintEditor::class)) {
299+
self::assertArrayHasKey($foreignKey->getReferencedTableName()->toString(), $expectedColumns);
295300

296-
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getForeignTableName()];
301+
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getReferencedTableName()->toString()];
297302

298-
self::assertSame($localColumns, $foreignKey->getLocalColumns());
299-
self::assertSame($foreignColumns, $foreignKey->getForeignColumns());
303+
self::assertSame($localColumns, array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencingColumnNames()));
304+
self::assertSame($foreignColumns, array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencedColumnNames()));
305+
} else {
306+
self::assertArrayHasKey($foreignKey->getForeignTableName(), $expectedColumns);
307+
308+
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getForeignTableName()];
309+
310+
self::assertSame($localColumns, $foreignKey->getLocalColumns());
311+
self::assertSame($foreignColumns, $foreignKey->getForeignColumns());
312+
}
300313
}
301314
}
302315

0 commit comments

Comments
 (0)