UUID7Factory.php
PHP
Path: src/UUID/UUID7Factory.php
<?php
namespace mini\UUID;
/**
* Generates UUID v7 identifiers using Unix timestamp (milliseconds) + cryptographically secure randomness.
*
* UUID v7 is a 128-bit time-ordered identifier formatted as a 36-character string:
* `xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx`
*
* Where:
* - First 48 bits: Unix timestamp in milliseconds (big-endian)
* - Next 4 bits: Version field (0111 = 7)
* - Next 12 bits: Random data (rand_a)
* - Next 2 bits: Variant field (10 = RFC 4122)
* - Last 62 bits: Random data (rand_b)
*
* ## Key Benefits
*
* - **Time-ordered**: Naturally sorts by creation time (lexicographically sortable)
* - **Database-friendly**: Better B-tree index performance than UUID v4
* - **Future-proof**: Valid until year ~10889 AD
* - **Unique**: 74 bits of cryptographic randomness per millisecond
*
* ## Specification
*
* Implements RFC 9562 Section 5.7
* https://datatracker.ietf.org/doc/rfc9562/
*
* ## Example Output
*
* ```
* 018c8f3a-2b4e-7a1c-9f23-4d5e6f7a8b9c
* ```
*
* Note: The first segment changes every ~4 days (2^32 milliseconds).
*/
class UUID7Factory implements FactoryInterface {
/**
* Generate a time-ordered UUID v7.
*
* @return string A UUID v7 string in standard format
* @throws \Random\RandomException If random_bytes() fails
*/
public function make(): string {
$timestamp = (int)(microtime(true) * 1000);
// Pack 48-bit timestamp into 52 bits (13 hex chars) with gaps for version nibble,
// then append 22 hex chars of randomness (11 bytes) for total of 35 chars
$uuid = dechex(
0xF0000000000000 | // Set high nibble (ensures 14 hex char output)
(($timestamp << 8) & 0x0FFFFFFF000000) | // Timestamp bits 20-47 → result bits 24-51
(($timestamp << 4) & 0x000000000FFFF0) // Timestamp bits 0-19 → result bits 4-23
) . bin2hex(random_bytes(11)); // Add 22 random hex chars
// Overwrite positions with formatting and version/variant bits
$uuid[0] = '0'; // Clear the 0xF marker we used
$uuid[8] = '-';
$uuid[13] = '-';
$uuid[14] = '7'; // Version 7
$uuid[18] = '-';
$uuid[19] = '89ab'[ord($uuid[19]) & 3]; // RFC 4122 variant
$uuid[23] = '-';
return $uuid;
}
}