UUID在PHP中的使用
0. 参考资料
这里是UUID标准信息:通用唯一识别码。
这里是pecl::uuid源代码。
如果下文描述与上述链接不符,请以链接中的信息为准。
1. 粗略理解UUID
- UUID是为了更方便的使用唯一标示符而被设计出来的。传统上,获得唯一标示符需要一个中心系统或某些协调机构以确保标示符的唯一性。这些方式并不方便分布式系统的运作。所以UUID被设计出来,可以去中心化地生成唯一标示符。
- UUID由开放软件基金会(Open Software Foundation, OSF)定义,之后互联网工程任务组公布了标准RFC 4122,国际电信联盟基于先前的标准和RFC 4122标准化了UUID。
- UUID是一个128位长的二进制字符串,共16字节,通常使用32个表示16进制数的字符表示并且用中横线“-”分割。标准格式为“8-4-4-4-12”,使用小写字符(列如:12345678-90ab-cdef-0123-456789abcdef)。
- 微软公司的GUID可以被视为UUID的一个变体,有时会使用大括号表示。具体情况请关注微软文档。
2. 如何在PHP中使用UUID
环境:
CentOS CentOS Linux release 7.9.2009
PHP 8.2.4
libuuid-devl 2.23.2
pecl::uuid 1.2.0
实际上PHP并没有像某些语言那样提供独立的UUID实现,而是通过打包libuuid支持UUID。CentOS的最小安装模式中已经包含了libuuid,如果必要可以通过yum
安装一下libuuid-devel(yum -y install libuuid-devel
)就好了。使用PHP pecl扩展需要需要在编译时加入--with-pear
参数或使用wget http://pear.php.net/go-pear.phar
和php go-pear.phar
命令独立安装PEAR。之后使用pecl install uuid
就可以安装UUID扩展,在php.ini中加入extention = uuid.so
配置后,可以通过php -m
命令验证UUID模块是否安装成功。
3. UUID函数介绍
1. uuid_create(int $uuid_type): string
用途: 创建一个UUID。
参数: 整形值,含义为要创建的UUID版本。有效的参数值为0、1和4。其中1和4代表两种UUID版本,0是默认值,当系统存在高质量随机数时提供版本4的UUID,否则提供版本1的UUID。
// 以下常量,可用为 `uuid_create` 函数的参数。 const UUID_TYPE_DEFAULT = 0; const UUID_TYPE_TIME = 1; const UUID_TYPE_DCE = 4; const UUID_TYPE_NAME = 1; const UUID_TYPE_RANDOM = 4;
返回值:
如果参数有效,则返回相应版本的UUID字符串。否则抛出警告信息并返回默认的UUID字符串。
说明:
由于libuuid只实现了UUID的版本1和版本4(不同版本 UUID 的差别,请参照通用唯一识别码的内容),因此 pecl::uuid定义的相关常量UUID_TYPE_TIME
映射了libuuid中的常量UUID_TYPE_DCE_TIME
,对应UUID版本1;常量UUID_TYPE_RANDOM
映射了libuuid中的常量UUID_TYPE_DCE_RANDOM
,对应UUID版本4,而另外的常量UUID_TYPE_NAME
和UUID_TYPE_DCE
虽然也做了定义,但同样映射到了libuuid中的UUID_TYPE_DCE_TIME
和UUID_TYPE_DCE_RANDOM
,可以使用但目前意义不大。
一般认为版本1的UUID发生重复的概率更小,几乎可以保证真正的唯一性,但考虑到泄露MAC带来的安全忧虑,大多数时候还是倾向于采用版本4的UUID。因此本函数建议的用法是uuid_create(UUID_TYPE_RANDOM)
或uuid_create()
。
2. uuid_is_valid(string $uuid ): bool
用途: 检查给定参数是否是一个有效的UUID。
参数: 字符串,待检查的UUID。
返回值:
如果$uuid是一个符有效的UUID,返回bool值true;
如果$uuid不是一个有效的UUID,返回bool值false。
3. uuid_compare(string $uuid1, string $uuid2): int
用途: 按字典顺序比较俩个UUID字符串。
参数: 俩个UUID字符串。
返回值:
如果$uuid1或$uuid2不是有效的UUID字符串,返回bool值false。
如果 $uuid1 < $uuid2,返回一个小于0的整数;
如果 $uuid1 = $uuid2,返回0;
如果 $uuid1 > $uuid2,返回一个大于0的整数。
4. uuid_is_null(string $uuid): bool
用途: 检查一个给定的UUID是否为NULL UUID。
参数: 字符串,待检查的UUID。
返回值:
如果$uuid不是有效的UUID,返回bool值false;
如果$uuid不是NULL UUID,返回bool值false;
如果$uuid是NULL UUID,返回bool值true。
说明:
像'00000000-0000-0000-0000-000000000000'这样所有位置均为0的UUID,被称为NULL UUID或Nil UUID。
5. uuid_type(string $uuid): int
用途: 检查$uuid的版本。
参数: 字符串,待检查的UUID。
返回值:
如果$uuid不是有效的UUID,返回bool值false;
如果$uuid是NULL UUID,返回int值-1;
如果$uuid是有效的UUID,根据UUID的版本,返回 1、2 3、4或5。
说明:
由于当前uuid_create()
不能生成2、3、5版本的 UUID,故未曾做相关测试。
6. uuid_variant(string $uuid): int
用途: 检查$uuid是何种UUID变体。
参数: 字符串,待检查的UUID。
返回值:
如果$uuid不是有效的UUID,返回bool值false;
如果$uuid是NULL UUID,返回int值-1;
根据$uuid 的变体类型,返回 0、1、2或3。
说明:
// 通过这些常量的名称,很容易理解返回值所代表的变体类型 const UUID_VARIANT_NCS = 0; const UUID_VARIANT_DCE = 1; const UUID_VARIANT_MICROSOFT = 2; const UUID_VARIANT_OTHER = 3;
(摘抄自通用唯一识别码)虽然一些重要的GUID名义上是变体2的UUID,例如组件对象模型(Component Object Model)IUnknown接口的标识符,但是在微软Windows软件中所生成和使用的、被称为“GUID”的许多标识符是使用标准的变体1的RFC 4122/DCE 1.1大端序UUID。目前,Microsoft guidgen工具软件产生变体1的结果。某些微软文档称GUID与UUID是同义词,如同RFC 4122中表示UUID“也被称作GUID”。这些文件表明了虽然“GUID”最初指代微软所使用的其中一种UUID变体,但现在已经成为UUID的另一个名称,含括变体1和2。
7. uuid_time(string $uuid): int
用途: 解析UUID,返回构造UUID所使用的UNIX时间戳。
参数: 字符串,带解析的UUID。
返回值:
如果$uuid不是有效的UUID,返回bool值false;
如果$uuid不是RFC 4122定义的变体类型1(uuid_variant()返回值为1,在libuuid中预定义的常量为UUID_VARIANT_DCE。),返回bool值false;
如果$uuid不是版本1的UUID,返回bool值false;
如果$uuid是版本1的UUID,返回构建UUID所使用的UNIX时间戳。
8. uuid_mac(string $uuid): string
用途: 解析UUID,返回构造UUID所使用的MAC地址。
参数: 字符串,待解析的UUID。
返回值:
如果$uuid不是有效的UUID,返回bool值false;
如果$uuid不是RFC 4122定义的变体类型1,返回bool值false;
如果$uuid不是版本1的UUID,返回bool值false;
如果$uuid中不含有有效的MAC地址,返回bool值false;
如果参数有效,返回返回构造UUID所使用的MAC地址,表达为一个12字符的16进制字符串。
9. uuid_parse(string $uuid): string
用途: 打包一个UUID为16字节的二进制字符串。
参数: 待打包的UUID。
返回值:
如果$uuid不是有效的UUID,返回bool值false;
如果$uuid是有效的UUID,返回对$uuid进行打包的二进制字符串。
说明:
打包过程,首先去除UUID字符串中的“-”符号,形成一个32字符的16进制数字字符串。再把每两字符所表达的16进制数打包成高位在前16进制数,构成16字节的字符串。相当于执行了一个pack操作。// uuid_parse和pack的对比验证 $strUUID = uuid_create(UUID_TYPE_RANDOM); echo '::UUID: ', $strUUID, PHP_EOL; $strParsed = uuid_parse($strUUID); $strPacked = pack("H*", str_replace('-', '', $strUUID)); echo '::Parsed: ', bin2hex($strParsed), PHP_EOL; echo '::Packed: ', bin2hex($strPacked), PHP_EOL;
10. uuid_unparse(string $uuid): string
用途: 把一个16字节的二进制字符串解析为UUID。
参数: 待解析的二进制字符串。
返回值:
如果参数数据有效,返回一个UUID字符串;
如果参数数据无效,返回bool值false。
说明:
uuid_unparse()
函数是uuid_parse()
函数的反过程。但下面的示例代码用pack()
函数替代了uuid_parse()
函数,近一步验证了前例。$strOriginalUUID = uuid_create(UUID_TYPE_RANDOM); echo '::Original UUID: ', $strOriginalUUID, PHP_EOL; $strPacked = pack("H*", str_replace('-', '', $strOriginalUUID)); $strUnparsedUUID = uuid_unparse($strPacked); echo '::Unparsed UUID: ', $strUnparsedUUID, PHP_EOL;