Skip to content

Commit 7db0e79

Browse files
committed
Fix Type Mismatch in Polymorphic Relationships When Using PostgreSQL
fixes #54401 Signed-off-by: Mior Muhammad Zaki <[email protected]>
1 parent 8509637 commit 7db0e79

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Database\Eloquent\Builder;
66
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Schema\Builder as SchemaBuilder;
78
use Illuminate\Support\Str;
89

910
/**
@@ -58,7 +59,18 @@ public function addConstraints()
5859
if (static::$constraints) {
5960
$this->getRelationQuery()->where($this->morphType, $this->morphClass);
6061

61-
parent::addConstraints();
62+
if (is_null(SchemaBuilder::$defaultMorphKeyType)) {
63+
parent::addConstraints();
64+
} else {
65+
$query = $this->getRelationQuery();
66+
67+
$query->where($this->foreignKey, '=', transform($this->getParentKey(), fn ($key) => match (SchemaBuilder::$defaultMorphKeyType) {
68+
'uuid', 'ulid', 'string' => (string) $key,
69+
default => $key,
70+
}));
71+
72+
$query->whereNotNull($this->foreignKey);
73+
}
6274
}
6375
}
6476

src/Illuminate/Database/Schema/Blueprint.php

+36
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,8 @@ public function morphs($name, $indexName = null)
14861486
$this->uuidMorphs($name, $indexName);
14871487
} elseif (Builder::$defaultMorphKeyType === 'ulid') {
14881488
$this->ulidMorphs($name, $indexName);
1489+
} elseif (Builder::$defaultMorphKeyType === 'string') {
1490+
$this->stringableMorphs($name, $indexName);
14891491
} else {
14901492
$this->numericMorphs($name, $indexName);
14911493
}
@@ -1504,11 +1506,45 @@ public function nullableMorphs($name, $indexName = null)
15041506
$this->nullableUuidMorphs($name, $indexName);
15051507
} elseif (Builder::$defaultMorphKeyType === 'ulid') {
15061508
$this->nullableUlidMorphs($name, $indexName);
1509+
} elseif (Builder::$defaultMorphKeyType === 'string') {
1510+
$this->nullableStringableMorphs($name, $indexName);
15071511
} else {
15081512
$this->nullableNumericMorphs($name, $indexName);
15091513
}
15101514
}
15111515

1516+
/**
1517+
* Add the proper columns for a polymorphic table using string as IDs (mixed of UUID/ULID & incremental integer).
1518+
*
1519+
* @param string $name
1520+
* @param string|null $indexName
1521+
* @return void
1522+
*/
1523+
public function stringableMorphs($name, $indexName = null)
1524+
{
1525+
$this->string("{$name}_type");
1526+
1527+
$this->string("{$name}_id");
1528+
1529+
$this->index(["{$name}_type", "{$name}_id"], $indexName);
1530+
}
1531+
1532+
/**
1533+
* Add nullable columns for a polymorphic table using string as IDs (mixed of UUID/ULID & incremental integer).
1534+
*
1535+
* @param string $name
1536+
* @param string|null $indexName
1537+
* @return void
1538+
*/
1539+
public function nullableStringableMorphs($name, $indexName = null)
1540+
{
1541+
$this->string("{$name}_type")->nullable();
1542+
1543+
$this->string("{$name}_id")->nullable();
1544+
1545+
$this->index(["{$name}_type", "{$name}_id"], $indexName);
1546+
}
1547+
15121548
/**
15131549
* Add the proper columns for a polymorphic table using numeric IDs (incremental).
15141550
*

src/Illuminate/Database/Schema/Builder.php

+15-4
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class Builder
4444
/**
4545
* The default relationship morph key type.
4646
*
47-
* @var string
47+
* @var string|null
4848
*/
49-
public static $defaultMorphKeyType = 'int';
49+
public static $defaultMorphKeyType = null;
5050

5151
/**
5252
* Create a new database Schema manager.
@@ -81,8 +81,8 @@ public static function defaultStringLength($length)
8181
*/
8282
public static function defaultMorphKeyType(string $type)
8383
{
84-
if (! in_array($type, ['int', 'uuid', 'ulid'])) {
85-
throw new InvalidArgumentException("Morph key type must be 'int', 'uuid', or 'ulid'.");
84+
if (! in_array($type, ['int', 'uuid', 'ulid', 'string'])) {
85+
throw new InvalidArgumentException("Morph key type must be 'int', 'uuid', 'ulid', or 'string'.");
8686
}
8787

8888
static::$defaultMorphKeyType = $type;
@@ -108,6 +108,17 @@ public static function morphUsingUlids()
108108
static::defaultMorphKeyType('ulid');
109109
}
110110

111+
/**
112+
* Set the default morph key type for migrations to string as IDs (mixed of UUID/ULID & incremental integer).
113+
*
114+
* @return void
115+
*/
116+
public static function morphUsingString()
117+
{
118+
static::defaultMorphKeyType('string');
119+
}
120+
121+
111122
/**
112123
* Create a database in the schema.
113124
*

tests/Database/DatabaseSchemaBlueprintTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class DatabaseSchemaBlueprintTest extends TestCase
1919
protected function tearDown(): void
2020
{
2121
m::close();
22-
Builder::$defaultMorphKeyType = 'int';
22+
Builder::$defaultMorphKeyType = null;
2323
}
2424

2525
public function testToSqlRunsCommandsFromBlueprint()

0 commit comments

Comments
 (0)