PHP function to generate v4 UUID
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:
xxxxxxxx-xxxx- 4 xxx- y xxx-xxxxxxxxxxxx
where y is 8, 9, A, or B. This is where the functions fails as it doesn't adhere to that.
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.
从这个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 )
);
}
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().
According to RFC 4122 - Section 4.4, you need to change these fields:
time_hi_and_version
(bits 4-7 of 7th octet), clock_seq_hi_and_reserved
(bit 6 & 7 of 9th octet) All of the other 122 bits should be sufficiently random.
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.
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()
:
echo guidv4(random_bytes(16));
Anyone using composer dependencies, you might want to consider this library: https://github.com/ramsey/uuid
It doesn't get any easier than this:
Uuid::uuid4();
链接地址: http://www.djcxy.com/p/91398.html
上一篇: 如何测试有效的UUID / GUID?
下一篇: PHP函数生成v4 UUID