Skip to content

Commit e257cd4

Browse files
Backport Uuid trait (#26)
Co-authored-by: Matt Inamdar <[email protected]>
1 parent 1a8269f commit e257cd4

14 files changed

+452
-25
lines changed

README.md

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ composer require goldspecdigital/laravel-eloquent-uuid:~v1.1
6060

6161
## Usage
6262

63+
There are two ways to use this package:
64+
1. By extending the provided model classes (preferred and simplest method).
65+
2. By using the provided model trait (allows for extending another model class).
66+
67+
### Extending model
68+
6369
When creating a Eloquent model, instead of extending the standard Laravel model
6470
class, extend from the model class provided by this package:
6571

@@ -76,7 +82,7 @@ class BlogPost extends Model
7682
}
7783
```
7884

79-
### User model
85+
### Extending user model
8086

8187
The User model that comes with a standard Laravel install has some extra
8288
configuration which is implemented in its parent class. This configuration only
@@ -98,13 +104,54 @@ class User extends Authenticatable
98104
}
99105
```
100106

107+
### Using trait
108+
109+
As an alternative to extending the classes in the examples above, you also have
110+
the ability to use the provided trait instead. This requires a more involved
111+
setup process but allows you to extend your models from another class if needed:
112+
113+
```php
114+
<?php
115+
116+
namespace App\Models;
117+
118+
use GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent\Uuid;
119+
use Illuminate\Database\Eloquent\Model;
120+
121+
class BlogPost extends Model
122+
{
123+
use Uuid;
124+
125+
/**
126+
* The "type" of the auto-incrementing ID.
127+
*
128+
* @var string
129+
*/
130+
protected $keyType = 'string';
131+
132+
/**
133+
* Indicates if the IDs are auto-incrementing.
134+
*
135+
* @var bool
136+
*/
137+
public $incrementing = false;
138+
139+
/**
140+
* The attributes that are mass assignable.
141+
*
142+
* @var array
143+
*/
144+
protected $guarded = [];
145+
}
146+
```
147+
101148
### Generating UUIDs
102149

103150
If you don't specify the value for the primary key of your model, a UUID will
104151
be automatically generated. However, if you do specify your own UUID then it
105-
will not generate one, but instead use the one you have explicitly provided. This
106-
can be useful when needing the know the ID of the model before you have created
107-
it:
152+
will not generate one, but instead use the one you have explicitly provided.
153+
This can be useful when needing the know the ID of the model before you have
154+
created it:
108155

109156
```php
110157
// No UUID provided (automatically generated).
@@ -119,7 +166,10 @@ echo $model->id; // 04d7f995-ef33-4870-a214-4e21c51ff76e
119166
### Specifying UUID versions
120167

121168
By default, `v4` UUIDs will be used for your models. However, you can also
122-
specify `v1` UUIDs to be used by setting the following property on your model:
169+
specify `v1` UUIDs to be used by setting the following property/method on your
170+
model:
171+
172+
#### When extending the class
123173

124174
```php
125175
<?php
@@ -139,6 +189,32 @@ class BlogPost extends Model
139189
}
140190
```
141191

192+
#### When using the trait
193+
194+
```php
195+
<?php
196+
197+
namespace App\Models;
198+
199+
use GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent\Uuid;
200+
use Illuminate\Database\Eloquent\Model;
201+
202+
class BlogPost extends Model
203+
{
204+
use Uuid;
205+
206+
/**
207+
* The UUID version to use.
208+
*
209+
* @return int
210+
*/
211+
protected function uuidVersion(): int
212+
{
213+
return 1;
214+
}
215+
}
216+
```
217+
142218
#### Support for `v3` and `v5`
143219

144220
Should you need support for `v3` or `v5` UUIDs, you can simply override the

src/Database/Eloquent/Uuid.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent;
6+
7+
use Exception;
8+
use Ramsey\Uuid\Uuid as RamseyUuid;
9+
10+
trait Uuid
11+
{
12+
/**
13+
* Indicates if the IDs are UUIDs.
14+
*
15+
* @return bool
16+
*/
17+
protected function keyIsUuid(): bool
18+
{
19+
return true;
20+
}
21+
22+
/**
23+
* The UUID version to use.
24+
*
25+
* @return int
26+
*/
27+
protected function uuidVersion(): int
28+
{
29+
return 4;
30+
}
31+
32+
/**
33+
* The "booting" method of the model.
34+
*/
35+
public static function bootUuid(): void
36+
{
37+
static::creating(function (self $model): void {
38+
// Automatically generate a UUID if using them, and not provided.
39+
if ($model->keyIsUuid() && empty($model->{$model->getKeyName()})) {
40+
$model->{$model->getKeyName()} = $model->generateUuid();
41+
}
42+
});
43+
}
44+
45+
/**
46+
* @throws \Exception
47+
* @return string
48+
*/
49+
protected function generateUuid(): string
50+
{
51+
switch ($this->uuidVersion()) {
52+
case 1:
53+
return RamseyUuid::uuid1()->toString();
54+
case 4:
55+
return RamseyUuid::uuid4()->toString();
56+
}
57+
58+
throw new Exception("UUID version [{$this->uuidVersion()}] not supported.");
59+
}
60+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace GoldSpecDigital\LaravelEloquentUUID\Tests\Database\Eloquent;
6+
7+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithUuid1;
8+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithUuid4;
9+
use GoldSpecDigital\LaravelEloquentUUID\Tests\TestCase;
10+
use Illuminate\Support\Str;
11+
12+
class ModelExtendingClassWithUuidTest extends TestCase
13+
{
14+
/** @test */
15+
public function it_generates_a_uuid1_when_the_id_has_not_been_set(): void
16+
{
17+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithUuid1 $testModel */
18+
$testModel = TestModelExtendingClassWithUuid1::query()->create();
19+
20+
$this->assertEquals(36, mb_strlen($testModel->id));
21+
}
22+
23+
/** @test */
24+
public function it_generates_a_uuid4_when_the_id_has_not_been_set(): void
25+
{
26+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithUuid4 $testModel */
27+
$testModel = TestModelExtendingClassWithUuid4::query()->create();
28+
29+
$this->assertEquals(36, mb_strlen($testModel->id));
30+
}
31+
32+
/** @test */
33+
public function it_uses_the_uuid1_provided_when_id_has_been_set(): void
34+
{
35+
$uuid = Str::uuid()->toString();
36+
37+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithUuid1 $testModel */
38+
$testModel = TestModelExtendingClassWithUuid1::query()->create([
39+
'id' => $uuid,
40+
]);
41+
42+
$this->assertEquals($uuid, $testModel->id);
43+
}
44+
45+
/** @test */
46+
public function it_uses_the_uuid4_provided_when_id_has_been_set(): void
47+
{
48+
$uuid = Str::uuid()->toString();
49+
50+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithUuid4 $testModel */
51+
$testModel = TestModelExtendingClassWithUuid4::query()->create([
52+
'id' => $uuid,
53+
]);
54+
55+
$this->assertEquals($uuid, $testModel->id);
56+
}
57+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace GoldSpecDigital\LaravelEloquentUUID\Tests\Database\Eloquent;
6+
7+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithoutUuid1;
8+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelExtendingClassWithoutUuid4;
9+
use GoldSpecDigital\LaravelEloquentUUID\Tests\TestCase;
10+
use PDOException;
11+
12+
class ModelExtendingClassWithoutUuidTest extends TestCase
13+
{
14+
/** @test */
15+
public function it_does_not_generate_a_uuid1_when_no_id_has_been_set(): void
16+
{
17+
$this->expectException(PDOException::class);
18+
19+
TestModelExtendingClassWithoutUuid1::query()->create();
20+
}
21+
22+
/** @test */
23+
public function it_does_not_generate_a_uuid4_when_no_id_has_been_set(): void
24+
{
25+
$this->expectException(PDOException::class);
26+
27+
TestModelExtendingClassWithoutUuid4::query()->create();
28+
}
29+
}

tests/Database/Eloquent/ModelWithUuidTest.php renamed to tests/Database/Eloquent/ModelUsingTraitWithUuidTest.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@
44

55
namespace GoldSpecDigital\LaravelEloquentUUID\Tests\Database\Eloquent;
66

7-
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithUuid1;
8-
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithUuid4;
7+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithUuid1;
8+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithUuid4;
99
use GoldSpecDigital\LaravelEloquentUUID\Tests\TestCase;
1010
use Illuminate\Support\Str;
1111

12-
class ModelWithUuidTest extends TestCase
12+
class ModelUsingTraitWithUuidTest extends TestCase
1313
{
1414
/** @test */
1515
public function it_generates_a_uuid1_when_the_id_has_not_been_set(): void
1616
{
17-
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithUuid1 $testModel */
18-
$testModel = TestModelWithUuid1::query()->create();
17+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithUuid1 $testModel */
18+
$testModel = TestModelUsingTraitWithUuid1::query()->create();
1919

2020
$this->assertEquals(36, mb_strlen($testModel->id));
2121
}
2222

2323
/** @test */
2424
public function it_generates_a_uuid4_when_the_id_has_not_been_set(): void
2525
{
26-
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithUuid4 $testModel */
27-
$testModel = TestModelWithUuid4::query()->create();
26+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithUuid4 $testModel */
27+
$testModel = TestModelUsingTraitWithUuid4::query()->create();
2828

2929
$this->assertEquals(36, mb_strlen($testModel->id));
3030
}
@@ -34,8 +34,8 @@ public function it_uses_the_uuid1_provided_when_id_has_been_set(): void
3434
{
3535
$uuid = Str::uuid()->toString();
3636

37-
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithUuid1 $testModel */
38-
$testModel = TestModelWithUuid1::query()->create([
37+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithUuid1 $testModel */
38+
$testModel = TestModelUsingTraitWithUuid1::query()->create([
3939
'id' => $uuid,
4040
]);
4141

@@ -47,8 +47,8 @@ public function it_uses_the_uuid4_provided_when_id_has_been_set(): void
4747
{
4848
$uuid = Str::uuid()->toString();
4949

50-
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithUuid4 $testModel */
51-
$testModel = TestModelWithUuid4::query()->create([
50+
/** @var \GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithUuid4 $testModel */
51+
$testModel = TestModelUsingTraitWithUuid4::query()->create([
5252
'id' => $uuid,
5353
]);
5454

tests/Database/Eloquent/ModelWithoutUuidTest.php renamed to tests/Database/Eloquent/ModelUsingTraitWithoutUuidTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@
44

55
namespace GoldSpecDigital\LaravelEloquentUUID\Tests\Database\Eloquent;
66

7-
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithoutUuid1;
8-
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelWithoutUuid4;
7+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithoutUuid1;
8+
use GoldSpecDigital\LaravelEloquentUUID\Tests\Models\TestModelUsingTraitWithoutUuid4;
99
use GoldSpecDigital\LaravelEloquentUUID\Tests\TestCase;
1010
use PDOException;
1111

12-
class ModelWithoutUuidTest extends TestCase
12+
class ModelUsingTraitWithoutUuidTest extends TestCase
1313
{
1414
/** @test */
1515
public function it_does_not_generate_a_uuid1_when_no_id_has_been_set(): void
1616
{
1717
$this->expectException(PDOException::class);
1818

19-
TestModelWithoutUuid1::query()->create();
19+
TestModelUsingTraitWithoutUuid1::query()->create();
2020
}
2121

2222
/** @test */
2323
public function it_does_not_generate_a_uuid4_when_no_id_has_been_set(): void
2424
{
2525
$this->expectException(PDOException::class);
2626

27-
TestModelWithoutUuid4::query()->create();
27+
TestModelUsingTraitWithoutUuid4::query()->create();
2828
}
2929
}

tests/Models/TestModelWithUuid1.php renamed to tests/Models/TestModelExtendingClassWithUuid1.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent\Model;
88

9-
class TestModelWithUuid1 extends Model
9+
class TestModelExtendingClassWithUuid1 extends Model
1010
{
1111
/**
1212
* The table associated with the model.
@@ -15,6 +15,7 @@ class TestModelWithUuid1 extends Model
1515
*/
1616
protected $table = 'test_model_with_uuids';
1717

18+
1819
/**
1920
* The UUID version to use.
2021
*

tests/Models/TestModelWithUuid4.php renamed to tests/Models/TestModelExtendingClassWithUuid4.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent\Model;
88

9-
class TestModelWithUuid4 extends Model
9+
class TestModelExtendingClassWithUuid4 extends Model
1010
{
1111
/**
1212
* The table associated with the model.

tests/Models/TestModelWithoutUuid1.php renamed to tests/Models/TestModelExtendingClassWithoutUuid1.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent\Model;
88

9-
class TestModelWithoutUuid1 extends Model
9+
class TestModelExtendingClassWithoutUuid1 extends Model
1010
{
1111
/**
1212
* The table associated with the model.

0 commit comments

Comments
 (0)