如何将PHP的UUID V4转换为两个64位整数

4

例子: 由PHP的v4生成的UUID: 8bc278cb-2fb6-413b-add6-8ba39bf830e8

我想将其转换为两个64位整数。

我尝试使用PHP的hexdec,但它返回的是数字类型。我需要整数类型。

有趣的是:

我尝试使用hexdec将上述uuid转换,并使用此输出进行dechex。但是,为什么没有得到相同的值呢?

如果您有任何见解,将不胜感激。


随机UUID(v4)总共有2^122种组合。而64位整数只有2^64种组合。后者似乎不可能包含前者中的所有可能数据。 - Koala Yeung
https://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates - Koala Yeung
这里是如何在PHP中将字节数组转换为浮点数。 - Syed Azhar Abbas
2个回答

5

UUID是一种128位的数据类型。除去6个保留位,它有122个数据位。这使得将任何UUID完全转换为64位整数变得不可能。您至少需要将其存储为2个64位数字或4个32位数字。

您可以将UUID解包成二进制格式,然后将其拆分为4个32位无符号字符:

function uuidToHex($uuid) {
    return str_replace('-', '', $uuid);
}

function hexToUuid($hex) {
    $regex = '/^([\da-f]{8})([\da-f]{4})([\da-f]{4})([\da-f]{4})([\da-f]{12})$/';
    return preg_match($regex, $hex, $matches) ?
        "{$matches[1]}-{$matches[2]}-{$matches[3]}-{$matches[4]}-{$matches[5]}" :
        FALSE;
}

function hexToIntegers($hex) {
    $bin = pack('h*', $hex);
    return unpack('L*', $bin);
}

function integersToHex($integers) {
    $args = $integers; $args[0] = 'L*'; ksort($args);
    $bin = call_user_func_array('pack', $args);
    $results = unpack('h*', $bin);
    return $results[1];
}

$uuid = '1968ec4a-2a73-11df-9aca-00012e27a270';
var_dump($uuid);

$integers = hexToIntegers(uuidToHex('1968ec4a-2a73-11df-9aca-00012e27a270'));
var_dump($integers);

$uuid = hexToUuid(integersToHex($integers));
var_dump($uuid);

它将返回
string(36) "1968ec4a-2a73-11df-9aca-00012e27a270"
array(4) {
  [1]=>
  int(2764998289)
  [2]=>
  int(4245764002)
  [3]=>
  int(268479657)
  [4]=>
  int(120222434)
}
string(36) "1968ec4a-2a73-11df-9aca-00012e27a270"

$integers是一个包含4个32位数字的数组,表示十六进制。

参考资料

  1. Stack Overflow: PHP中规范UUID表示的16字节二进制形式
  2. Stack Overflow: 如何在PHP中将字节数组转换为整数?
  3. PHP手册: pack()

我已经尝试重新组合从您的函数返回的两个64位整数的十六进制值。它与“1968ec4a-2a73-11df-9aca-00012e27a270”不匹配。理想情况下,它应该匹配。 - riser101
你能给我展示一下你用来将两个64位整数重新格式化为十六进制的代码吗? - Koala Yeung

3
尽管在其他语言中(如Java)获取UUID的最低有效位和最高有效位作为两个无符号64位整数是很常见的,但PHP会遇到问题,因为PHP中所有整数都是有符号的。即使使用64位的PHP版本,当尝试获取UUID的最低或最高有效位的实际整数值时,也会遇到整数溢出的问题。
64位PHP的最大整数值为9,223,372,036,854,775,807,而一个无符号的64位整数的最大值为18,446,744,073,709,551,615。一个UUID作为两个64位整数需要支持高达18,446,744,073,709,551,615的值。
正如早些时候的答案所提到的,如果需要像这样拆分UUID,则将其拆分为四个无符号32位整数可能更好。(无符号32位整数的最大值为4,294,967,295,64位PHP可以支持。)

如果您只是想以更优化的方式存储UUID,可以将其转换为16字节的二进制字符串:

$uuid = '1968ec4a-2a73-11df-9aca-00012e27a270';

$binaryUuid = hex2bin(str_replace('-', '', $uuid));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接