oittaa / uuid
一个用于从版本 3 到版本 8 生成 RFC 9562 通用唯一识别码 (UUID) 的 PHP 类。
1.10
2024-07-10 20:19 UTC
Requires
- php: ^8.1
Requires (Dev)
- phpunit/phpunit: ^10.0
README
uuid-php
一个用于生成从版本 3 到版本 8 的 RFC 9562 通用唯一识别码 (UUID) 的 PHP 类。
如果您只需要一个唯一的标识符,您应该调用 uuid4()
。
实现应尽可能使用 UUIDv7 而不是 UUIDv1 和 UUIDv6。
如果您经常每秒生成超过一千个 UUID,您可能想使用 uuid8()
而不是 uuid7()
。与 uuid7()
相比,此 uuid8()
实现牺牲了一些熵,但提供了 100 纳秒的粒度,在其他方面兼容。
最小 UUID v4 实现
此最小 RFC 9562 兼容解决方案的功劳归于 Stackoverflow 上的此答案:https://stackoverflow.com/a/15875555。
<?php function uuid4() { $data = random_bytes(16); $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100 $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10 return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } echo uuid4();
最小 UUID v7 实现
<?php function uuid7() { static $last_timestamp = 0; $unixts_ms = intval(microtime(true) * 1000); if ($last_timestamp >= $unixts_ms) { $unixts_ms = $last_timestamp + 1; } $last_timestamp = $unixts_ms; $data = random_bytes(10); $data[0] = chr((ord($data[0]) & 0x0f) | 0x70); // set version $data[2] = chr((ord($data[2]) & 0x3f) | 0x80); // set variant return vsprintf( '%s%s-%s-%s-%s-%s%s%s', str_split( str_pad(dechex($unixts_ms), 12, '0', \STR_PAD_LEFT) . bin2hex($data), 4 ) ); } echo uuid7();
安装
如果您需要比较工具或可排序的标识符,如版本 6、7 和 8 中的,您可能会发现这个小型且快速的包很有用。它不需要任何其他依赖。
composer require oittaa/uuid
使用
如何生成
<?php require 'vendor/autoload.php'; use UUID\UUID; // Generate a version 3 (name-based and hashed with MD5) UUID // Namespaces: NAMESPACE_DNS, NAMESPACE_URL, NAMESPACE_OID, NAMESPACE_X500 $uuid3 = UUID::uuid3(UUID::NAMESPACE_DNS, 'php.net'); echo $uuid3 . "\n"; // 11a38b9a-b3da-360f-9353-a5a725514269 // Generate a version 4 (random) UUID $uuid4 = UUID::uuid4(); echo $uuid4 . "\n"; // e.g. 2140a926-4a47-465c-b622-4571ad9bb378 // Generate a version 5 (name-based and hashed with SHA1) UUID $uuid5 = UUID::uuid5(UUID::NAMESPACE_DNS, 'php.net'); echo $uuid5 . "\n"; // c4a760a8-dbcf-5254-a0d9-6a4474bd1b62 // Generate a version 6 (lexicographically sortable) UUID $uuid6_first = UUID::uuid6(); echo $uuid6_first . "\n"; // e.g. 1ec9414c-232a-6b00-b3c8-9e6bdeced846 $uuid6_second = UUID::uuid6(); var_dump($uuid6_first < $uuid6_second); // bool(true) // Generate a version 7 (lexicographically sortable) UUID $uuid7_first = UUID::uuid7(); echo $uuid7_first . "\n"; // e.g. 017f22e2-79b0-7cc3-98c4-dc0c0c07398f $uuid7_second = UUID::uuid7(); var_dump($uuid7_first < $uuid7_second); // bool(true) // Generate a version 8 (lexicographically sortable) UUID $uuid8_first = UUID::uuid8(); echo $uuid8_first . "\n"; // e.g. 017f22e2-79b0-8cc3-98c4-dc0c0c07398f $uuid8_second = UUID::uuid8(); var_dump($uuid8_first < $uuid8_second); // bool(true)
工具
<?php require 'vendor/autoload.php'; use UUID\UUID; // Test if a given string is a valid UUID $isvalid = UUID::isValid('11a38b9a-b3da-360f-9353-a5a725514269'); var_dump($isvalid); // bool(true) // The string standard representation of the UUID. $tostring = UUID::toString('{C4A760A8-DBCF-5254-A0D9-6A4474BD1B62}'); var_dump($tostring); // string(36) "c4a760a8-dbcf-5254-a0d9-6a4474bd1b62" // Test if two UUIDs are equal $equals1 = UUID::equals( 'c4a760a8-dbcf-5254-a0d9-6a4474bd1b62', '2140a926-4a47-465c-b622-4571ad9bb378' ); var_dump($equals1); // bool(false) $equals2 = UUID::equals( 'c4a760a8-dbcf-5254-a0d9-6a4474bd1b62', 'C4A760A8-DBCF-5254-A0D9-6A4474BD1B62' ); var_dump($equals2); // bool(true) $equals3 = UUID::equals( 'urn:uuid:c4a760a8-dbcf-5254-a0d9-6a4474bd1b62', '{C4A760A8-DBCF-5254-A0D9-6A4474BD1B62}' ); var_dump($equals3); // bool(true) // UUID comparison. Returns < 0 if uuid1 is less than uuid2; // > 0 if uuid1 is greater than uuid2, and 0 if they are equal. $cmp1 = UUID::cmp( '11a38b9a-b3da-360f-9353-a5a725514269', '2140a926-4a47-465c-b622-4571ad9bb378' ); var_dump($cmp1 < 0); // bool(true) $cmp2 = UUID::cmp( 'c4a760a8-dbcf-5254-a0d9-6a4474bd1b62', '2140a926-4a47-465c-b622-4571ad9bb378' ); var_dump($cmp2 > 0); // bool(true) $cmp3 = UUID::cmp( 'urn:uuid:c4a760a8-dbcf-5254-a0d9-6a4474bd1b62', '{C4A760A8-DBCF-5254-A0D9-6A4474BD1B62}' ); var_dump($cmp3 === 0); // bool(true) // Extract Unix time from versions 6, 7, and 8 as a string. $uuid6_time = UUID::getTime('1ec9414c-232a-6b00-b3c8-9e6bdeced846'); var_dump($uuid6_time); // string(18) "1645557742.0000000" $uuid7_time = UUID::getTime('017f22e2-79b0-7cc3-98c4-dc0c0c07398f'); var_dump($uuid7_time); // string(18) "1645557742.0000000" $uuid8_time = UUID::getTime('017f22e2-79b0-8cc3-98c4-dc0c0c07398f'); var_dump($uuid8_time); // string(18) "1645557742.0007977" // Extract the UUID version. $uuid_version = UUID::getVersion('2140a926-4a47-465c-b622-4571ad9bb378'); var_dump($uuid_version); // int(4)
UUIDv6 字段和位布局
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_high |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_mid | time_low_and_version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|clk_seq_hi_res | clk_seq_low | node (0-1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| node (2-5) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
UUIDv7 字段和位布局
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | rand_a |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
UUIDv8 字段和位布局
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | subsec |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|sub| rand |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rand |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
unix_ts_ms
:48 位大端无符号数字,表示具有毫秒级精度的 Unix 纪元时间戳ver
:4 位 UUIDv8 版本(1000)subsec
:12 位分配给次秒精度值var
:2 位 UUID 变体(10)sub
:2 位分配给次秒精度值rand
:剩余的 60 位用伪随机数据填充
14 位专门用于次秒精度,提供 100 纳秒分辨率。《unix_ts_ms》和《subsec》字段通过单调递增计时器保证同一时间戳生成的 UUID 的顺序。