Skip to content

rafalswierczek/uuid4

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Super simple UUID v4 generator in PHP

Installation:

composer require rafalswierczek/uuid4

Usage:

$uuid4 = Uuid4Factory::create();

$uuid4 = new Uuid4('f3d7fa06-d938-4c22-9505-c585efa381df');

$uuid4 = new Uuid4(Uuid4Factory::createBinary()->toHex());

$uuid4 = new Uuid4(Uuid4Factory::create()->toHex());

$uuid4Binary = Uuid4Factory::createBinary();

$uuid4Binary = new Uuid4Binary(random_bytes(16));

$uuid4Binary = new Uuid4Binary(Uuid4Factory::createBinary()->toBinary());

$uuid4Binary = new Uuid4Binary(Uuid4Factory::create()->toBinary());

// example 1:
$userClass = new class()
{
    private Uuid4Interface $uuid4;

    public function getUuid(bool $toHex = true): string
    {
        return $toHex ? $this->uuid4->toHex() : $this->uuid4->toBinary();
    }

    public function setUuid(Uuid4Interface $uuid4): void
    {
        $this->uuid4 = $uuid4;
    }
};

$userClass->setUuid(Uuid4Factory::createBinary());
$uuid4 = $userClass->getUuid(toHex: true); // hex format

// example 2:
$unknownSource = 'f3d7fa06-d938-4c22-9505-c585efaxxxxx';
Uuid4::validate($unknownSource);

// example 3:
$uuid4 = new Uuid4('f3d7fa06-d938-4c22-9505-c585efa381df'); // this also calls validate method because it is VO
$uuid4Binary = new Uuid4Binary($uuid4->toBinary());         // this also calls validate method because it is VO
$hexEqualsBin = $uuid4->equals($uuid4Binary);
$binEqualsHex = $uuid4Binary->equals($uuid4);

Explanation:

UUID v4 is data of 128 random bits (with small modifications) represented in hexadecimal notation.

Data is divided into 16 octets (from 0 to 15), 8 bits each.

Octets are grouped into sections with following names:

  • time_low (octets 0-3)
  • time_mid (octets 4-5)
  • time_high_and_version (octets 6-7)
  • clock_seq_and_reserved (octet 8)
  • clock_seq_low (octet 9)
  • node (octets 10-15)

Result of UUID4 in hex notation looks like this:

f2e0aa63-22f2-410c-bcfa-9475cf573193

As you can see, for example time_low has 4 octets, each is as follows f2, e0, aa, 63 in hex notation.

Now once you have 128 random bits, you have to modify octet 8 in the way that two most significant bits (MSB) are set to: 0 and 1. For example, let's say 8 octet is as follows: 01101101. Now you have to make sure that two bits on the left are 00 and then you can add desired 10 so the result is: 10101101. It's done this way:

01101101 & 00111111 = 00101101

00101101 | 10000000 = 10101101

Once clock_seq_and_reserved is updated it's time to modify octet 6 (first 8 bits of time_high_and_version). You have to do the same steps but with 00001111 for AND and 01000000 for OR. For example if octet 6 is 10100101, the result is 01000101 so first 4 bits are replaced with 0100 which are bits reserved for UUID v4.

After modifying octet 8 and 6 of 128 random bits and converting it to hex notation you have ready to use UUID v4 string :)

RFC: https://datatracker.ietf.org/doc/html/rfc4122#section-4.4