php PHP函数生成v4 UUID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2040240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP function to generate v4 UUID
提问by anomareh
So I've been doing some digging around and I've been trying to piece together a function that generates a valid v4 UUID in PHP. This is the closest I've been able to come. My knowledge in hex, decimal, binary, PHP's bitwise operators and the like is nearly non existant. This function generates a valid v4 UUID up until one area. A v4 UUID should be in the form of:
所以我一直在做一些挖掘,我一直在尝试拼凑一个在 PHP 中生成有效 v4 UUID 的函数。这是我离得最近的一次。我在十六进制、十进制、二进制、PHP 的按位运算符等方面的知识几乎不存在。此函数生成一个有效的 v4 UUID,直到一个区域。v4 UUID 应采用以下形式:
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
XXXXXXXX-XXXX- 4XXX- ýXXX-XXXXXXXXXXXX
where yis 8, 9, A, or B. This is where the functions fails as it doesn't adhere to that.
其中y是 8、9、A 或 B。这是函数失败的地方,因为它不遵守这一点。
I was hoping someone with more knowledge than me in this area could lend me a hand and help me fix this function so it does adhere to that rule.
我希望在这方面比我有更多知识的人可以帮助我并帮助我修复此功能,因此它确实遵守该规则。
The function is as follows:
功能如下:
<?php
function gen_uuid() {
$uuid = array(
'time_low' => 0,
'time_mid' => 0,
'time_hi' => 0,
'clock_seq_hi' => 0,
'clock_seq_low' => 0,
'node' => array()
);
$uuid['time_low'] = mt_rand(0, 0xffff) + (mt_rand(0, 0xffff) << 16);
$uuid['time_mid'] = mt_rand(0, 0xffff);
$uuid['time_hi'] = (4 << 12) | (mt_rand(0, 0x1000));
$uuid['clock_seq_hi'] = (1 << 7) | (mt_rand(0, 128));
$uuid['clock_seq_low'] = mt_rand(0, 255);
for ($i = 0; $i < 6; $i++) {
$uuid['node'][$i] = mt_rand(0, 255);
}
$uuid = sprintf('%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x',
$uuid['time_low'],
$uuid['time_mid'],
$uuid['time_hi'],
$uuid['clock_seq_hi'],
$uuid['clock_seq_low'],
$uuid['node'][0],
$uuid['node'][1],
$uuid['node'][2],
$uuid['node'][3],
$uuid['node'][4],
$uuid['node'][5]
);
return $uuid;
}
?>
Thanks to anyone that can help me out.
感谢任何可以帮助我的人。
回答by Ja?ck
Instead of breaking it down into individual fields, it's easier to generate a random block of data and change the individual byte positions. You should also use a better random number generator than mt_rand().
生成随机数据块并更改单个字节位置比将其分解为单个字段更容易。您还应该使用比 mt_rand() 更好的随机数生成器。
According to RFC 4122 - Section 4.4, you need to change these fields:
根据RFC 4122 - Section 4.4,您需要更改这些字段:
time_hi_and_version(bits 4-7 of 7th octet),clock_seq_hi_and_reserved(bit 6 & 7 of 9th octet)
time_hi_and_version(第 7 个八位字节的第 4-7 位),clock_seq_hi_and_reserved(第 9 个八位字节的第 6 位和第 7 位)
All of the other 122 bits should be sufficiently random.
所有其他 122 位都应该足够随机。
The following approach generates 128 bits of random data using openssl_random_pseudo_bytes(), makes the permutations on the octets and then uses bin2hex()and vsprintf()to do the final formatting.
以下方法使用 生成 128 位随机数据openssl_random_pseudo_bytes(),对八位字节进行排列,然后使用bin2hex()和vsprintf()进行最终格式化。
function guidv4($data)
{
assert(strlen($data) == 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 guidv4(openssl_random_pseudo_bytes(16));
With PHP 7, generating random byte sequences is even simpler using random_bytes():
使用 PHP 7,生成随机字节序列更加简单random_bytes():
function guidv4($data = null)
{
$data = $data ?? random_bytes(16);
// ...
}
回答by William
Taken from thiscomment on the PHP manual, you could use this:
取自PHP 手册上的此评论,您可以使用它:
function gen_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
// 32 bits for "time_low"
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
// 16 bits for "time_mid"
mt_rand( 0, 0xffff ),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
mt_rand( 0, 0x0fff ) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
mt_rand( 0, 0x3fff ) | 0x8000,
// 48 bits for "node"
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
);
}
回答by djule5
Anyone using composerdependencies, you might want to consider this library: https://github.com/ramsey/uuid
任何使用作曲家依赖项的人,您可能需要考虑这个库:https: //github.com/ramsey/uuid
It doesn't get any easier than this:
没有比这更容易的了:
Uuid::uuid4();
回答by ThorSummoner
on unix systems, use the system kernel to generate a uuid for you.
在 unix 系统上,使用系统内核为您生成一个 uuid。
file_get_contents('/proc/sys/kernel/random/uuid')
Credit Samveen on https://serverfault.com/a/529319/210994
在https://serverfault.com/a/529319/210994上信用 Samveen
Note!: Using this method to get a uuid does in fact exhaust the entropy pool, very quickly! I would avoid using this where it would be called frequently.
注意!:使用这种方法获取 uuid 确实会很快耗尽熵池!我会避免在经常调用它的地方使用它。
回答by Arie
In my search for a creating a v4 uuid, I came first to this page, then found this on http://php.net/manual/en/function.com-create-guid.php
在我寻找创建 v4 uuid 的过程中,我首先来到这个页面,然后在http://php.net/manual/en/function.com-create-guid.php上找到了这个
function guidv4()
{
if (function_exists('com_create_guid') === true)
return trim(com_create_guid(), '{}');
$data = openssl_random_pseudo_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));
}
credit: pavel.volyntsev
信用:pavel.volyntsev
Edit: to clarify, this function will always give you a v4 uuid (PHP >= 5.3.0).
编辑:澄清一下,此函数将始终为您提供 v4 uuid(PHP >= 5.3.0)。
When the com_create_guid function is available (usually only on Windows), it will use that and strip the curly braces.
当 com_create_guid 函数可用时(通常只在 Windows 上),它将使用它并去掉花括号。
If not present (Linux), it will fall back on this strong random openssl_random_pseudo_bytes function, it will then uses vsprintf to format it into v4 uuid.
如果不存在 (Linux),它将依靠这个强大的随机 openssl_random_pseudo_bytes 函数,然后使用 vsprintf 将其格式化为 v4 uuid。
回答by bish
回答by Danny Beckett
A slight variation on Hyman's answerto add support for PHP < 7:
// Get an RFC-4122 compliant globaly unique identifier
function get_guid() {
$data = PHP_MAJOR_VERSION < 7 ? openssl_random_pseudo_bytes(16) : 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));
}
回答by Victor Smirnov
My answer is based on comment uniqid user commentbut it uses openssl_random_pseudo_bytesfunction to generate random string instead of reading from /dev/urandom
我的回答基于评论uniqid 用户评论,但它使用openssl_random_pseudo_bytes函数生成随机字符串而不是从/dev/urandom
function guid()
{
$randomString = openssl_random_pseudo_bytes(16);
$time_low = bin2hex(substr($randomString, 0, 4));
$time_mid = bin2hex(substr($randomString, 4, 2));
$time_hi_and_version = bin2hex(substr($randomString, 6, 2));
$clock_seq_hi_and_reserved = bin2hex(substr($randomString, 8, 2));
$node = bin2hex(substr($randomString, 10, 6));
/**
* Set the four most significant bits (bits 12 through 15) of the
* time_hi_and_version field to the 4-bit version number from
* Section 4.1.3.
* @see http://tools.ietf.org/html/rfc4122#section-4.1.3
*/
$time_hi_and_version = hexdec($time_hi_and_version);
$time_hi_and_version = $time_hi_and_version >> 4;
$time_hi_and_version = $time_hi_and_version | 0x4000;
/**
* Set the two most significant bits (bits 6 and 7) of the
* clock_seq_hi_and_reserved to zero and one, respectively.
*/
$clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved);
$clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2;
$clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000;
return sprintf('%08s-%04s-%04x-%04x-%012s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node);
} // guid
回答by MichaelRushton
Inspired by broofa's answer here.
preg_replace_callback('/[xy]/', function ($matches)
{
return dechex('x' == $matches[0] ? mt_rand(0, 15) : (mt_rand(0, 15) & 0x3 | 0x8));
}
, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');
Or if unable to use anonymous functions.
或者如果无法使用匿名函数。
preg_replace_callback('/[xy]/', create_function(
'$matches',
'return dechex("x" == $matches[0] ? mt_rand(0, 15) : (mt_rand(0, 15) & 0x3 | 0x8));'
)
, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');
回答by indextwo
Having searched for the exact same thing and almostimplementing a version of this myself, I thought it was worth mentioning that, if you're doing this within a WordPressframework, WP has its own super-handy function for exactly this:
在搜索了完全相同的东西并几乎自己实现了一个版本后,我认为值得一提的是,如果您在WordPress框架中执行此操作,WP 有自己的超级方便的功能:
$myUUID = wp_generate_uuid4();
$myUUID = wp_generate_uuid4();
You can read the description and the source here.
您可以在此处阅读说明和来源。

