Skip to content

Commit 71dfdc0

Browse files
Fix schema foreign ID support for tables with non-standard primary key (#53442)
* Add test for constrained foreign keys * Add failing test * Set the referenced column name based on the model key name * Use the referenced column name if available * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent cd86694 commit 71dfdc0

File tree

4 files changed

+54
-4
lines changed

4 files changed

+54
-4
lines changed

src/Illuminate/Database/Schema/Blueprint.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,16 +1039,22 @@ public function foreignIdFor($model, $column = null)
10391039
$column = $column ?: $model->getForeignKey();
10401040

10411041
if ($model->getKeyType() === 'int' && $model->getIncrementing()) {
1042-
return $this->foreignId($column)->table($model->getTable());
1042+
return $this->foreignId($column)
1043+
->table($model->getTable())
1044+
->referencesModelColumn($model->getKeyName());
10431045
}
10441046

10451047
$modelTraits = class_uses_recursive($model);
10461048

10471049
if (in_array(HasUlids::class, $modelTraits, true)) {
1048-
return $this->foreignUlid($column, 26)->table($model->getTable());
1050+
return $this->foreignUlid($column, 26)
1051+
->table($model->getTable())
1052+
->referencesModelColumn($model->getKeyName());
10491053
}
10501054

1051-
return $this->foreignUuid($column)->table($model->getTable());
1055+
return $this->foreignUuid($column)
1056+
->table($model->getTable())
1057+
->referencesModelColumn($model->getKeyName());
10521058
}
10531059

10541060
/**

src/Illuminate/Database/Schema/ForeignIdColumnDefinition.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ public function __construct(Blueprint $blueprint, $attributes = [])
3535
* @param string|null $indexName
3636
* @return \Illuminate\Database\Schema\ForeignKeyDefinition
3737
*/
38-
public function constrained($table = null, $column = 'id', $indexName = null)
38+
public function constrained($table = null, $column = null, $indexName = null)
3939
{
4040
$table ??= $this->table;
41+
$column ??= $this->referencesModelColumn ?? 'id';
4142

4243
return $this->references($column, $indexName)->on($table ?? Str::of($this->name)->beforeLast('_'.$column)->plural());
4344
}

tests/Database/DatabaseSchemaBlueprintTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Illuminate\Database\Schema\Grammars\PostgresGrammar;
1111
use Illuminate\Database\Schema\Grammars\SQLiteGrammar;
1212
use Illuminate\Database\Schema\Grammars\SqlServerGrammar;
13+
use Illuminate\Tests\Database\Fixtures\Models\User;
1314
use Mockery as m;
1415
use PHPUnit\Framework\TestCase;
1516

@@ -444,6 +445,38 @@ public function testGenerateRelationshipColumnWithUlidModel()
444445
], $blueprint->toSql($connection, new MySqlGrammar()));
445446
}
446447

448+
public function testGenerateRelationshipConstrainedColumn()
449+
{
450+
$base = new Blueprint('posts', function ($table) {
451+
$table->foreignIdFor('Illuminate\Foundation\Auth\User')->constrained();
452+
});
453+
454+
$connection = m::mock(Connection::class);
455+
456+
$blueprint = clone $base;
457+
458+
$this->assertEquals([
459+
'alter table `posts` add `user_id` bigint unsigned not null',
460+
'alter table `posts` add constraint `posts_user_id_foreign` foreign key (`user_id`) references `users` (`id`)',
461+
], $blueprint->toSql($connection, new MySqlGrammar));
462+
}
463+
464+
public function testGenerateRelationshipForModelWithNonStandardPrimaryKeyName()
465+
{
466+
$base = new Blueprint('posts', function ($table) {
467+
$table->foreignIdFor(User::class)->constrained();
468+
});
469+
470+
$connection = m::mock(Connection::class);
471+
472+
$blueprint = clone $base;
473+
474+
$this->assertEquals([
475+
'alter table `posts` add `user_internal_id` bigint unsigned not null',
476+
'alter table `posts` add constraint `posts_user_internal_id_foreign` foreign key (`user_internal_id`) references `users` (`internal_id`)',
477+
], $blueprint->toSql($connection, new MySqlGrammar));
478+
}
479+
447480
public function testDropRelationshipColumnWithIncrementalModel()
448481
{
449482
$base = new Blueprint('posts', function ($table) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Database\Fixtures\Models;
4+
5+
use Illuminate\Foundation\Auth\User as FoundationUser;
6+
7+
class User extends FoundationUser
8+
{
9+
protected $primaryKey = 'internal_id';
10+
}

0 commit comments

Comments
 (0)