Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/Command/ModelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -1587,7 +1587,16 @@ protected function ensureAliasUniqueness(array $associations): array
foreach ($associationsPerType as $k => $association) {
$alias = $association['alias'];
if (in_array($alias, $existing, true)) {
$alias = $this->createAssociationAlias($association);
// Derive a unique alias by appending a numeric suffix.
// Self-referencing keys (e.g. `system_id` on `systems`)
// would otherwise yield the same colliding alias again.
$base = $this->createAssociationAlias($association);
$alias = $base;
$i = 1;
while (in_array($alias, $existing, true)) {
$i++;
$alias = $base . $i;
}
}
$existing[] = $alias;
if (empty($association['className'])) {
Expand Down
29 changes: 29 additions & 0 deletions tests/TestCase/Command/ModelCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,35 @@ public function testApplyAssociationsConcreteClass(): void
$this->assertEquals($original, $new);
}

/**
* A non-foreign-key column matching the table name (e.g. `system_id` on
* `systems`) must not produce duplicate aliases that break baking.
*
* @return void
*/
public function testGetAssociationsEnsuresUniqueAliasForSelfReferencingKey(): void
{
$systems = $this->getTableLocator()->get('Systems');

$command = new ModelCommand();
$command->connection = 'test';
$args = new Arguments([], [], []);
$io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($systems, $args, $io);

$belongsToAliases = array_column($result['belongsTo'], 'alias');
$hasManyAliases = array_column($result['hasMany'], 'alias');
$allAliases = array_merge($belongsToAliases, $hasManyAliases);

$this->assertContains('Systems', $belongsToAliases);
$this->assertContains('Systems2', $hasManyAliases);
$this->assertSame($allAliases, array_unique($allAliases), 'Association aliases must be unique.');

// Applying the deduplicated associations must not throw.
$command->applyAssociations($systems, $result);
$this->assertSame(['Systems', 'Systems2'], $systems->associations()->keys());
}

/**
* Test getAssociations
*
Expand Down
11 changes: 11 additions & 0 deletions tests/schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,17 @@
'unique_self_referencing_parent' => ['type' => 'unique', 'columns' => ['parent_id']],
],
],
// "systems" has a "system_id" column that is not a real foreign key.
// It would otherwise produce duplicate "Systems" belongsTo/hasMany aliases.
[
'table' => 'systems',
'columns' => [
'id' => ['type' => 'integer'],
'system_id' => ['type' => 'string', 'length' => 255, 'null' => false],
'name' => ['type' => 'string', 'length' => 255, 'null' => true],
],
'constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]],
],
// "news" is both singular and plural - tests variable collision fix
[
'table' => 'news',
Expand Down
Loading