Skip to content

Commit 3b3979c

Browse files
Merge branch 'diegomagikal-multiple_uuids'
2 parents 49c56c6 + 87e5219 commit 3b3979c

8 files changed

+148
-41
lines changed

.travis.yml

-14
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,6 @@ cache:
66

77
matrix:
88
include:
9-
- php: 7.1
10-
env: ILLUMINATE_VERSION=5.6.*
11-
- php: 7.2
12-
env: ILLUMINATE_VERSION=5.6.*
13-
- php: 7.1
14-
env: ILLUMINATE_VERSION=5.7.*
15-
- php: 7.2
16-
env: ILLUMINATE_VERSION=5.7.*
17-
- php: 7.1
18-
env: ILLUMINATE_VERSION=5.8.*
19-
- php: 7.2
20-
env: ILLUMINATE_VERSION=5.8.*
21-
- php: 7.3
22-
env: ILLUMINATE_VERSION=5.8.*
239
- php: 7.2
2410
env: ILLUMINATE_VERSION=6.*
2511
- php: 7.3

README.md

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Laravel Model UUIDs
2-
## v4.1.0
2+
## v5.0.0
33

44
[![Build Status](https://travis-ci.org/michaeldyrynda/laravel-model-uuid.svg?branch=master)](https://travis-ci.org/michaeldyrynda/laravel-model-uuid)
55
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/michaeldyrynda/laravel-model-uuid/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/michaeldyrynda/laravel-model-uuid/?branch=master)
@@ -44,13 +44,25 @@ It is assumed that you already have a field named `uuid` in your database, which
4444
```php
4545
class Post extends Model
4646
{
47-
public function uuidColumn()
47+
public function uuidColumn(): string
4848
{
4949
return 'custom_column';
5050
}
5151
}
5252
```
5353

54+
You can have multiple UUID columns in each table by specifying an array in the `uuidColumns` method. When querying using the `whereUuid` scope, the default column - specified by `uuidColumn` will be used.
55+
56+
```php
57+
class Post extends Model
58+
{
59+
public function uuidColumns(): array
60+
{
61+
return ['uuid', 'custom_column'];
62+
}
63+
}
64+
```
65+
5466
By default, this package will use UUID version 4 values, however, you are welcome to use `uuid1`, `uuid3`, `uuid4`, or `uuid5` by specifying the protected property `$uuidVersion` in your model. Should you wish to take advantage of ordered UUID (version 4) values that were introduced in Laravel 5.6, you should specify `ordered` as the `$uuidVersion` in your model.
5567

5668
```php
@@ -72,7 +84,17 @@ class Post extends Model
7284
This trait also provides a query scope which will allow you to easily find your records based on their UUID, and respects any custom field name you choose.
7385

7486
```php
87+
// Find a specific post with the default (uuid) column name
7588
$post = Post::whereUuid($uuid)->first();
89+
90+
// Find multiple posts with the default (uuid) column name
91+
$post = Post::whereUuid([$first, $second])->get();
92+
93+
// Find a specific post with a custom column name
94+
$post = Post::whereUuid($uuid, 'custom_column')->first();
95+
96+
// Find multiple posts with a custom column name
97+
$post = Post::whereUuid([$first, $second], 'custom_column')->get();
7698
```
7799

78100
If you use the suggested [laravel-efficient-uuid](https://github.com/michaeldyrynda/laravel-efficient-uuid) package, you will need to add a cast to your model in order to correctly set and retrieve your UUID values. This will ensure your UUIDs are written to your (MySQL) database as binary and presented as strings.
@@ -124,7 +146,7 @@ public function boot()
124146
This package is installed via [Composer](https://getcomposer.org/). To install, run the following command.
125147

126148
```bash
127-
composer require "dyrynda/laravel-model-uuid:~4.1"
149+
composer require dyrynda/laravel-model-uuid
128150
```
129151
## Support
130152

composer.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
}
1717
],
1818
"require": {
19-
"php": "^7.1.3",
20-
"illuminate/database": "~5.6|^6.0",
21-
"illuminate/events": "~5.6|^6.0",
22-
"illuminate/support": "~5.6|^6.0",
19+
"php": "^7.2",
20+
"illuminate/database": "^6.0",
21+
"illuminate/events": "^6.0",
22+
"illuminate/support": "^6.0",
2323
"ramsey/uuid": "~3.7",
2424
"moontoast/math": "^1.1"
2525
},
@@ -29,7 +29,7 @@
2929
}
3030
},
3131
"require-dev": {
32-
"phpunit/phpunit": "^7.0"
32+
"phpunit/phpunit": "^8.0"
3333
},
3434
"autoload-dev": {
3535
"psr-4": {

src/GeneratesUuid.php

+52-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
namespace Dyrynda\Database\Support;
44

55
use Ramsey\Uuid\Uuid;
6+
use Illuminate\Support\Arr;
67
use Illuminate\Support\Str;
8+
use Illuminate\Database\Eloquent\Builder;
9+
use Illuminate\Contracts\Support\Arrayable;
710

811
/**
912
* UUID generation trait.
@@ -50,18 +53,18 @@ abstract public function hasCast($key, $types = null);
5053
*
5154
* @return void
5255
*/
53-
public static function bootGeneratesUuid()
56+
public static function bootGeneratesUuid(): void
5457
{
5558
static::creating(function ($model) {
5659
/* @var \Illuminate\Database\Eloquent\Model|static $model */
5760
$uuid = $model->resolveUuid();
58-
59-
if (isset($model->attributes[$model->uuidColumn()]) && ! is_null($model->attributes[$model->uuidColumn()])) {
60-
/* @var \Ramsey\Uuid\Uuid $uuid */
61-
$uuid = $uuid->fromString(strtolower($model->attributes[$model->uuidColumn()]));
61+
foreach ($model->uuidColumns() as $item) {
62+
if (isset($model->attributes[$item]) && ! is_null($model->attributes[$item])) {
63+
/* @var \Ramsey\Uuid\Uuid $uuid */
64+
$uuid = $uuid->fromString(strtolower($model->attributes[$item]));
65+
}
66+
$model->attributes[$item] = $model->hasCast($item, 'uuid') ? $uuid->getBytes() : $uuid->toString();
6267
}
63-
64-
$model->attributes[$model->uuidColumn()] = $model->hasCast($model->uuidColumn(), 'uuid') ? $uuid->getBytes() : $uuid->toString();
6568
});
6669
}
6770

@@ -70,17 +73,27 @@ public static function bootGeneratesUuid()
7073
*
7174
* @return string
7275
*/
73-
public function uuidColumn()
76+
public function uuidColumn(): string
7477
{
7578
return 'uuid';
7679
}
7780

81+
/**
82+
* The names of the columns that should be used for the UUID.
83+
*
84+
* @return array
85+
*/
86+
public function uuidColumns(): array
87+
{
88+
return [$this->uuidColumn()];
89+
}
90+
7891
/**
7992
* Resolve a UUID instance for the configured version.
8093
*
8194
* @return \Ramsey\Uuid\Uuid
8295
*/
83-
public function resolveUuid()
96+
public function resolveUuid(): Uuid
8497
{
8598
if (($version = $this->resolveUuidVersion()) == 'ordered') {
8699
return Str::orderedUuid();
@@ -94,7 +107,7 @@ public function resolveUuid()
94107
*
95108
* @return string
96109
*/
97-
public function resolveUuidVersion()
110+
public function resolveUuidVersion(): string
98111
{
99112
if (property_exists($this, 'uuidVersion') && in_array($this->uuidVersion, $this->uuidVersions)) {
100113
return $this->uuidVersion;
@@ -108,16 +121,40 @@ public function resolveUuidVersion()
108121
*
109122
* @param \Illuminate\Database\Eloquent\Builder $query
110123
* @param string $uuid
124+
* @param string $uuidColumn
111125
*
112126
* @return \Illuminate\Database\Eloquent\Builder
113127
*/
114-
public function scopeWhereUuid($query, $uuid)
128+
public function scopeWhereUuid($query, $uuid, $uuidColumn = null): Builder
129+
{
130+
$uuidColumn = ! is_null($uuidColumn) && in_array($uuidColumn, $this->uuidColumns())
131+
? $uuidColumn
132+
: $this->uuidColumns()[0];
133+
134+
if ($this->hasCast($uuidColumn)) {
135+
$uuid = $this->bytesFromUuid($uuid);
136+
}
137+
138+
return $query->whereIn($uuidColumn, Arr::wrap($uuid));
139+
}
140+
141+
/**
142+
* Convert a single UUID or array of UUIDs to bytes
143+
*
144+
* @param \Illuminate\Contracts\Support\Arrayable|array|string $uuid
145+
* @return array
146+
*/
147+
protected function bytesFromUuid($uuid): array
115148
{
116-
if ($this->hasCast($this->uuidColumn())) {
117-
$uuid = $this->resolveUuid()->fromString($uuid)->getBytes();
149+
if (is_array($uuid) || $uuid instanceof Arrayable) {
150+
array_walk($uuid, function (&$uuid) {
151+
$uuid = $this->resolveUuid()->fromString($uuid)->getBytes();
152+
});
153+
154+
return $uuid;
118155
}
119156

120-
return $query->where($this->uuidColumn(), $uuid);
157+
return Arr::wrap($this->resolveUuid()->fromString($uuid)->getBytes());
121158
}
122159

123160
/**
@@ -129,7 +166,7 @@ public function scopeWhereUuid($query, $uuid)
129166
*/
130167
protected function castAttribute($key, $value)
131168
{
132-
if ($key === $this->uuidColumn() && ! is_null($value)) {
169+
if (in_array($key, $this->uuidColumns()) && ! empty($value)) {
133170
return $this->resolveUuid()->fromBytes($value)->toString();
134171
}
135172

tests/Feature/UuidTest.php

+48-2
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
use Illuminate\Events\Dispatcher;
1010
use Tests\Fixtures\CustomUuidPost;
1111
use Illuminate\Container\Container;
12+
use Tests\Fixtures\MultipleUuidPost;
1213
use Tests\Fixtures\CustomCastUuidPost;
1314
use Illuminate\Database\Capsule\Manager;
1415

1516
class UuidTest extends TestCase
1617
{
17-
public static function setupBeforeClass()
18+
public static function setupBeforeClass(): void
1819
{
1920
$manager = new Manager;
2021
$manager->addConnection(['driver' => 'sqlite', 'database' => ':memory:']);
@@ -55,12 +56,57 @@ public function you_can_find_a_model_by_its_uuid()
5556

5657
Post::create(['title' => 'test post', 'uuid' => $uuid]);
5758

58-
$post = Post::whereUuid(strtoupper($uuid))->first();
59+
$post = Post::whereUuid($uuid)->first();
5960

6061
$this->assertInstanceOf(Post::class, $post);
6162
$this->assertSame($uuid, $post->uuid);
6263
}
6364

65+
/** @test */
66+
public function you_can_find_a_model_by_custom_uuid_parameter()
67+
{
68+
$uuid = '6499332d-25e1-4d75-bd92-c6ded0820fb3';
69+
$custom_uuid = '99635d83-05bc-424f-bf3f-395ea7a5b323';
70+
71+
MultipleUuidPost::create(['title' => 'test post', 'uuid' => $uuid, 'custom_uuid' => $custom_uuid]);
72+
73+
$post1 = MultipleUuidPost::whereUuid($uuid)->first();
74+
$this->assertInstanceOf(MultipleUuidPost::class, $post1);
75+
$this->assertSame($uuid, $post1->uuid);
76+
77+
$post2 = MultipleUuidPost::whereUuid($uuid, 'uuid')->first();
78+
$this->assertInstanceOf(MultipleUuidPost::class, $post2);
79+
$this->assertSame($uuid, $post2->uuid);
80+
81+
$post3 = MultipleUuidPost::whereUuid($custom_uuid, 'custom_uuid')->first();
82+
$this->assertInstanceOf(MultipleUuidPost::class, $post3);
83+
$this->assertSame($custom_uuid, $post3->custom_uuid);
84+
}
85+
86+
/** @test */
87+
public function you_can_search_by_array_of_uuids()
88+
{
89+
$first = Post::create(['title' => 'first post', 'uuid' => '8ab48e77-d9cd-4fe7-ace5-a5a428590c18']);
90+
$second = Post::create(['title' => 'second post', 'uuid' => 'c7c26456-ddb0-45cd-9b1c-318296cce7a3']);
91+
92+
$this->assertEquals(2, Post::whereUuid([
93+
'8ab48e77-d9cd-4fe7-ace5-A5A428590C18',
94+
'c7c26456-ddb0-45cd-9b1c-318296cce7a3',
95+
])->count());
96+
}
97+
98+
/** @test */
99+
public function you_can_search_by_array_of_uuids_for_custom_column()
100+
{
101+
$first = CustomCastUuidPost::create(['title' => 'first post', 'custom_uuid' => '8ab48e77-d9cd-4fe7-ace5-a5a428590c18']);
102+
$second = CustomCastUuidPost::create(['title' => 'second post', 'custom_uuid' => 'c7c26456-ddb0-45cd-9b1c-318296cce7a3']);
103+
104+
$this->assertEquals(2, CustomCastUuidPost::whereUuid([
105+
'8ab48e77-d9cd-4fe7-ace5-A5A428590C18',
106+
'c7c26456-ddb0-45cd-9b1c-318296cce7a3',
107+
], 'custom_uuid')->count());
108+
}
109+
64110
/** @test */
65111
public function you_can_generate_a_uuid_without_casting()
66112
{

tests/Fixtures/CustomCastUuidPost.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class CustomCastUuidPost extends Model
99
*/
1010
protected $casts = ['custom_uuid' => 'uuid'];
1111

12-
public function uuidColumn()
12+
public function uuidColumn(): string
1313
{
1414
return 'custom_uuid';
1515
}

tests/Fixtures/CustomUuidPost.php

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

55
class CustomUuidPost extends Model
66
{
7-
public function uuidColumn()
7+
public function uuidColumn(): string
88
{
99
return 'custom_uuid';
1010
}

tests/Fixtures/MultipleUuidPost.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Tests\Fixtures;
4+
5+
class MultipleUuidPost extends Model
6+
{
7+
/**
8+
* {@inheritdoc}
9+
*/
10+
protected $casts = ['uuid' => 'uuid', 'custom_uuid' => 'uuid'];
11+
12+
public function uuidColumns(): array
13+
{
14+
return ['uuid', 'custom_uuid'];
15+
}
16+
}

0 commit comments

Comments
 (0)