Skip to content

Commit b2f3dca

Browse files
authored
Merge pull request #321 from binaryfire/fix/has-uuids-explicit-id
fix: `HasUuids` and `HasUlids` traits ignoring explicit IDs
2 parents 2c0e513 + 2d7c948 commit b2f3dca

File tree

6 files changed

+196
-2
lines changed

6 files changed

+196
-2
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@
216216
"phpunit/phpunit": "10.5.45",
217217
"pusher/pusher-php-server": "^7.2",
218218
"swoole/ide-helper": "~5.1.0",
219+
"symfony/uid": "^7.4",
219220
"symfony/yaml": "^7.3"
220221
},
221222
"config": {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait HasUlids
1414
public function creating(): void
1515
{
1616
foreach ($this->uniqueIds() as $column) {
17-
if (empty($model->{$column})) {
17+
if (empty($this->{$column})) {
1818
$this->{$column} = $this->newUniqueId();
1919
}
2020
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait HasUuids
1414
public function creating(): void
1515
{
1616
foreach ($this->uniqueIds() as $column) {
17-
if (empty($model->{$column})) {
17+
if (empty($this->{$column})) {
1818
$this->{$column} = $this->newUniqueId();
1919
}
2020
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hypervel\Tests\Core\Database\Eloquent\Concerns;
6+
7+
use Hyperf\Stringable\Str;
8+
use Hypervel\Database\Eloquent\Concerns\HasUlids;
9+
use Hypervel\Database\Eloquent\Model;
10+
use Hypervel\Foundation\Testing\RefreshDatabase;
11+
use Hypervel\Testbench\TestCase;
12+
13+
/**
14+
* @internal
15+
* @coversNothing
16+
*/
17+
class HasUlidsTest extends TestCase
18+
{
19+
use RefreshDatabase;
20+
21+
protected bool $migrateRefresh = true;
22+
23+
protected function migrateFreshUsing(): array
24+
{
25+
return [
26+
'--database' => $this->getRefreshConnection(),
27+
'--realpath' => true,
28+
'--path' => __DIR__ . '/migrations',
29+
];
30+
}
31+
32+
public function testAutoGeneratesUlidWhenNotProvided(): void
33+
{
34+
$model = HasUlidsTestModel::create(['name' => 'Test']);
35+
36+
$this->assertNotNull($model->id);
37+
$this->assertTrue(Str::isUlid($model->id));
38+
}
39+
40+
public function testRespectsExplicitUlidWhenProvided(): void
41+
{
42+
$explicitId = strtolower((string) Str::ulid());
43+
44+
$model = HasUlidsTestModel::create([
45+
'id' => $explicitId,
46+
'name' => 'Test',
47+
]);
48+
49+
$this->assertSame($explicitId, $model->id);
50+
}
51+
52+
public function testRespectsExplicitUlidInFirstOrCreate(): void
53+
{
54+
$explicitId = strtolower((string) Str::ulid());
55+
56+
$model = HasUlidsTestModel::firstOrCreate(
57+
['id' => $explicitId],
58+
['name' => 'Test']
59+
);
60+
61+
$this->assertSame($explicitId, $model->id);
62+
}
63+
}
64+
65+
class HasUlidsTestModel extends Model
66+
{
67+
use HasUlids;
68+
69+
protected ?string $table = 'has_ulids_test_models';
70+
71+
protected array $fillable = ['id', 'name'];
72+
73+
public bool $timestamps = true;
74+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hypervel\Tests\Core\Database\Eloquent\Concerns;
6+
7+
use Hyperf\Stringable\Str;
8+
use Hypervel\Database\Eloquent\Concerns\HasUuids;
9+
use Hypervel\Database\Eloquent\Model;
10+
use Hypervel\Foundation\Testing\RefreshDatabase;
11+
use Hypervel\Testbench\TestCase;
12+
13+
/**
14+
* @internal
15+
* @coversNothing
16+
*/
17+
class HasUuidsTest extends TestCase
18+
{
19+
use RefreshDatabase;
20+
21+
protected bool $migrateRefresh = true;
22+
23+
protected function migrateFreshUsing(): array
24+
{
25+
return [
26+
'--database' => $this->getRefreshConnection(),
27+
'--realpath' => true,
28+
'--path' => __DIR__ . '/migrations',
29+
];
30+
}
31+
32+
public function testAutoGeneratesUuidWhenNotProvided(): void
33+
{
34+
$model = HasUuidsTestModel::create(['name' => 'Test']);
35+
36+
$this->assertNotNull($model->id);
37+
$this->assertTrue(Str::isUuid($model->id));
38+
}
39+
40+
public function testRespectsExplicitUuidWhenProvided(): void
41+
{
42+
$explicitId = (string) Str::orderedUuid();
43+
44+
$model = HasUuidsTestModel::create([
45+
'id' => $explicitId,
46+
'name' => 'Test',
47+
]);
48+
49+
$this->assertSame($explicitId, $model->id);
50+
}
51+
52+
public function testRespectsExplicitUuidInFirstOrCreate(): void
53+
{
54+
$explicitId = (string) Str::orderedUuid();
55+
56+
$model = HasUuidsTestModel::firstOrCreate(
57+
['id' => $explicitId],
58+
['name' => 'Test']
59+
);
60+
61+
$this->assertSame($explicitId, $model->id);
62+
}
63+
64+
public function testDoesNotOverwriteIdOnExistingRecord(): void
65+
{
66+
$explicitId = (string) Str::orderedUuid();
67+
68+
// Create first
69+
HasUuidsTestModel::create([
70+
'id' => $explicitId,
71+
'name' => 'Original',
72+
]);
73+
74+
// firstOrCreate should find existing, not create new
75+
$model = HasUuidsTestModel::firstOrCreate(
76+
['id' => $explicitId],
77+
['name' => 'Should Not Be Used']
78+
);
79+
80+
$this->assertSame($explicitId, $model->id);
81+
$this->assertSame('Original', $model->name);
82+
}
83+
}
84+
85+
class HasUuidsTestModel extends Model
86+
{
87+
use HasUuids;
88+
89+
protected ?string $table = 'has_uuids_test_models';
90+
91+
protected array $fillable = ['id', 'name'];
92+
93+
public bool $timestamps = true;
94+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Hyperf\Database\Migrations\Migration;
6+
use Hyperf\Database\Schema\Blueprint;
7+
use Hyperf\Database\Schema\Schema;
8+
9+
return new class extends Migration {
10+
public function up(): void
11+
{
12+
// Use string(36) for UUID and string(26) for ULID for SQLite compatibility
13+
Schema::create('has_uuids_test_models', function (Blueprint $table) {
14+
$table->string('id', 36)->primary();
15+
$table->string('name');
16+
$table->timestamps();
17+
});
18+
19+
Schema::create('has_ulids_test_models', function (Blueprint $table) {
20+
$table->string('id', 26)->primary();
21+
$table->string('name');
22+
$table->timestamps();
23+
});
24+
}
25+
};

0 commit comments

Comments
 (0)