Skip to content

Commit 9235af3

Browse files
driesvintsStyleCIBottaylorotwell
authored
[9.x] Improve UUID and ULID support for Eloquent (#44146)
* Add ulid column type to Blueprint * Improve uuid and ulid support * Apply fixes from StyleCI * Adjust test * wip * formatting Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: Taylor Otwell <[email protected]>
1 parent 85ca3fb commit 9235af3

File tree

8 files changed

+173
-94
lines changed

8 files changed

+173
-94
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasUlids.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,10 @@ public function uniqueIds()
4949
*/
5050
public function getKeyType()
5151
{
52-
return 'string';
53-
}
52+
if (in_array($this->getKeyName(), $this->uniqueIds())) {
53+
return 'string';
54+
}
5455

55-
/**
56-
* Get the value indicating whether the IDs are incrementing.
57-
*
58-
* @return bool
59-
*/
60-
public function getIncrementing()
61-
{
62-
return false;
56+
return $this->keyType;
6357
}
6458
}

src/Illuminate/Database/Eloquent/Concerns/HasUuids.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,10 @@ public function uniqueIds()
4949
*/
5050
public function getKeyType()
5151
{
52-
return 'string';
53-
}
52+
if (in_array($this->getKeyName(), $this->uniqueIds())) {
53+
return 'string';
54+
}
5455

55-
/**
56-
* Get the value indicating whether the IDs are incrementing.
57-
*
58-
* @return bool
59-
*/
60-
public function getIncrementing()
61-
{
62-
return false;
56+
return $this->keyType;
6357
}
6458
}

src/Illuminate/Database/Eloquent/Model.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,10 @@ public function setKeyType($type)
18511851
*/
18521852
public function getIncrementing()
18531853
{
1854+
if ($this->getKeyType() === 'string') {
1855+
return false;
1856+
}
1857+
18541858
return $this->incrementing;
18551859
}
18561860

src/Illuminate/Database/Schema/Blueprint.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ public function binary($column)
12431243
}
12441244

12451245
/**
1246-
* Create a new uuid column on the table.
1246+
* Create a new UUID column on the table.
12471247
*
12481248
* @param string $column
12491249
* @return \Illuminate\Database\Schema\ColumnDefinition
@@ -1267,6 +1267,34 @@ public function foreignUuid($column)
12671267
]));
12681268
}
12691269

1270+
/**
1271+
* Create a new ULID column on the table.
1272+
*
1273+
* @param string $column
1274+
* @param int|null $length
1275+
* @return \Illuminate\Database\Schema\ColumnDefinition
1276+
*/
1277+
public function ulid($column = 'uuid', $length = 26)
1278+
{
1279+
return $this->char($column, $length);
1280+
}
1281+
1282+
/**
1283+
* Create a new ULID column on the table with a foreign key constraint.
1284+
*
1285+
* @param string $column
1286+
* @param int|null $length
1287+
* @return \Illuminate\Database\Schema\ForeignIdColumnDefinition
1288+
*/
1289+
public function foreignUlid($column, $length = 26)
1290+
{
1291+
return $this->addColumnDefinition(new ForeignIdColumnDefinition($this, [
1292+
'type' => 'char',
1293+
'name' => $column,
1294+
'length' => $length,
1295+
]));
1296+
}
1297+
12701298
/**
12711299
* Create a new IP address column on the table.
12721300
*

tests/Database/DatabaseEloquentModelTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2214,8 +2214,10 @@ public function testIntKeyTypePreserved()
22142214
public function testStringKeyTypePreserved()
22152215
{
22162216
$model = $this->getMockBuilder(EloquentKeyTypeModelStub::class)->onlyMethods(['newModelQuery', 'updateTimestamps', 'refresh'])->getMock();
2217+
$model->id = 'string id';
2218+
22172219
$query = m::mock(Builder::class);
2218-
$query->shouldReceive('insertGetId')->once()->with([], 'id')->andReturn('string id');
2220+
$query->shouldReceive('insert')->once()->with(['id' => 'string id']);
22192221
$query->shouldReceive('getConnection')->once();
22202222
$model->expects($this->once())->method('newModelQuery')->willReturn($query);
22212223

tests/Integration/Database/EloquentUlidPrimaryKeyTest.php

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Database;
4+
5+
use Illuminate\Database\Eloquent\Concerns\HasUlids;
6+
use Illuminate\Database\Eloquent\Concerns\HasUuids;
7+
use Illuminate\Database\Eloquent\Model as Eloquent;
8+
use Illuminate\Database\Schema\Blueprint;
9+
use Illuminate\Support\Facades\Schema;
10+
use Illuminate\Support\Str;
11+
12+
class EloquentUniqueStringPrimaryKeysTest extends DatabaseTestCase
13+
{
14+
protected function defineDatabaseMigrationsAfterDatabaseRefreshed()
15+
{
16+
Schema::create('users', function (Blueprint $table) {
17+
$table->uuid('id')->primary();
18+
$table->uuid('foo');
19+
$table->uuid('bar');
20+
$table->timestamps();
21+
});
22+
23+
Schema::create('posts', function (Blueprint $table) {
24+
$table->ulid('id')->primary();
25+
$table->ulid('foo');
26+
$table->ulid('bar');
27+
$table->timestamps();
28+
});
29+
30+
Schema::create('songs', function (Blueprint $table) {
31+
$table->id();
32+
$table->uuid('foo');
33+
$table->uuid('bar');
34+
$table->timestamps();
35+
});
36+
37+
Schema::create('pictures', function (Blueprint $table) {
38+
$table->uuid('uuid')->primary();
39+
$table->timestamps();
40+
});
41+
}
42+
43+
public function testModelWithUuidPrimaryKeyCanBeCreated()
44+
{
45+
$user = ModelWithUuidPrimaryKey::create();
46+
47+
$this->assertTrue(Str::isUuid($user->id));
48+
$this->assertTrue(Str::isUuid($user->foo));
49+
$this->assertTrue(Str::isUuid($user->bar));
50+
}
51+
52+
public function testModelWithUlidPrimaryKeyCanBeCreated()
53+
{
54+
$user = ModelWithUlidPrimaryKey::create();
55+
56+
$this->assertTrue(Str::isUlid($user->id));
57+
$this->assertTrue(Str::isUlid($user->foo));
58+
$this->assertTrue(Str::isUlid($user->bar));
59+
}
60+
61+
public function testModelWithoutUuidPrimaryKeyCanBeCreated()
62+
{
63+
$user = ModelWithoutUuidPrimaryKey::create();
64+
65+
$this->assertTrue(is_int($user->id));
66+
$this->assertTrue(Str::isUuid($user->foo));
67+
$this->assertTrue(Str::isUuid($user->bar));
68+
}
69+
70+
public function testModelWithCustomUuidPrimaryKeyNameCanBeCreated()
71+
{
72+
$user = ModelWithCustomUuidPrimaryKeyName::create();
73+
74+
$this->assertTrue(Str::isUuid($user->uuid));
75+
}
76+
}
77+
78+
class ModelWithUuidPrimaryKey extends Eloquent
79+
{
80+
use HasUuids;
81+
82+
protected $table = 'users';
83+
84+
protected $guarded = [];
85+
86+
public function uniqueIds()
87+
{
88+
return [$this->getKeyName(), 'foo', 'bar'];
89+
}
90+
}
91+
92+
class ModelWithUlidPrimaryKey extends Eloquent
93+
{
94+
use HasUlids;
95+
96+
protected $table = 'posts';
97+
98+
protected $guarded = [];
99+
100+
public function uniqueIds()
101+
{
102+
return [$this->getKeyName(), 'foo', 'bar'];
103+
}
104+
}
105+
106+
class ModelWithoutUuidPrimaryKey extends Eloquent
107+
{
108+
use HasUuids;
109+
110+
protected $table = 'songs';
111+
112+
protected $guarded = [];
113+
114+
public function uniqueIds()
115+
{
116+
return ['foo', 'bar'];
117+
}
118+
}
119+
120+
class ModelWithCustomUuidPrimaryKeyName extends Eloquent
121+
{
122+
use HasUuids;
123+
124+
protected $table = 'pictures';
125+
126+
protected $guarded = [];
127+
128+
protected $primaryKey = 'uuid';
129+
}

tests/Integration/Database/EloquentUuidPrimaryKeyTest.php

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)