4

I have two tables, one for lists and another that stores a history of lists that were created. These lists are very temporary and they can be deleted by numerous methods so I add a reason field on the history for that.

//Lists table
Schema::create('lists', function (Blueprint $table) {
  $table->increments('id');
  $table->string('name');
  $table->text('message');
  $table->uuid('uuid');
  $table->timestamps();
});

//History table
Schema::create('history', function (Blueprint $table) {
  $table->increments('id');
  $table->string('name');
  $table->text('message');
  $table->string('reason');
  $table->uuid('uuid');
  $table->timestamps();
});

Now both have a uuid field and I can generate an actual string to store with Laravel's helper function $uuid = (string) Str::uuid();

$list = new List;
$list->name = 'A basic fact of life';
$list->message = 'Pineapple does not belong on pizza.'
$uuid = (string) Str::uuid();
$list->uuid = $uuid;
$list->save();

Now when I successfully delete a record from Lists, I additionally create a new record in the history with its data.

$list = find($id);
$destroy = List::destroy($id);
if($destroy) {
  $history = new History;
  $history->name = $list->name;
  $history->message $list->message;
  $history->uuid = $list->uuid;
  $history->reason = 'some reason';
  $history->save();
}

So my question is, how will Laravel know that the next UUID I generate is actually unique?

The so called duplicate question linked doesn't actually say how or whether it knows the next UUID is actually unique to the past ones created but rather gives a probability.

ProEvilz
  • 5,310
  • 9
  • 44
  • 74

3 Answers3

11

Laravel implements UUID v4, defined by RFC 4122 to be unique. The RFC states (emphasis mine):

Identifier uniqueness considerations:
This document specifies three algorithms to generate UUIDs: the first leverages the unique values of 802 MAC addresses to guarantee uniqueness, the second uses pseudo-random number generators, and the third uses cryptographic hashing and application-provided text strings. As a result, the UUIDs generated according to the mechanisms here will be unique from all other UUIDs that have been or will be assigned.

Laravel doesn't so much "know" that it's unique, but rather "trusts" it is because the algorithm is defined to be unique with respect to all others generated by that algorithm.

There's an important caveat here. The algorithm requires a sufficient entropy source to guarantee the commonly cited claim that you'd need to create trillions a day for the next 100 years to have a 50/50 chance of a dupe. To that end, Laravel leans on ramsey/uuid to do the actual v4 generation. ramsey/uuid uses, long story short, random_bytes for its entropy. This is a cryptographically strong source, sufficient to qualify for v4 generation per the RFC. Now the important part:

If none of the aforementioned sources are available, then an Exception will be thrown.

So your code, where you do (string)Str::uuid() will throw an exception when it can't generate a truly random, globally unique value.

Community
  • 1
  • 1
bishop
  • 37,830
  • 11
  • 104
  • 139
2

UUID is short for “universal unique identifier” which is a set of 36 characters, containing letters and numbers. Each set should be unique, with there only being a chance for repetition each 100 years, you can read more about it and check out some cool statistics here and here.

Source: What is a UUID

Emtiaz Zahid
  • 2,645
  • 2
  • 19
  • 35
  • But how does it know it really hasn't been created before? It seems.. it doesn't, but rather that it's just unlikely? – ProEvilz Oct 11 '18 at 03:04
  • it doesn't check all your data to be unique. its actually generate a unique id. like random number algorithms does not repeat them self instantly – Emtiaz Zahid Oct 11 '18 at 03:08
  • 2
    UUIDv3/4/5 do not strictly guarantee uniqueness, but the odds of colloision are far smaller than the odds of you winning the lottery, getting struck by lightning and eaten by a shark *at the same time*. If you don't worry about that scenario, then dont worry about collisions either. – StephenS Nov 03 '18 at 21:14
1

As per previous comments, the UUID generated by Laravel will rarely repeat. The least you could do is to have a db check if that UUID exists. So when you are creating a new list you could have something like this.

for($i=0; $i<5; $i++)
{

$uuid = (string) Str::uuid();
if(!DB::table('lists')->where('uuid',$uuid)->first())
{
$list = new List;
$list->name = 'A basic fact of life';
$list->message = 'Pineapple does not belong on pizza.'
$uuid = (string) Str::uuid();
$list->uuid = $uuid;
$list->save();

break;
}

}


This will run the for loop for once and chances of it running for another time is same as chances of uuid repeating itself which is after a trillion times per sec for 100 years...

This will make sure that your uuid is always unique, though it might add some extra time because of db call but if you are happy sacrificing some ms here and there then this might be one of the approach to ensure every uuid is unique.

adir1521
  • 124
  • 2
  • 12