首先,我也会选择自动增量。即使您选择使用提到的代码(月份+随机内容),我也建议您使用数字(int/bigint)自动增量 id。您应该使用此 id '在表面之下'让您的代码与数据库进行通信(引用/查找记录)。
因此,对于“月份+随机内容”标识符,我不建议使用任何东西,uniqid()
因为它基于微秒,如果两个事务将在同一微秒发生,则不是唯一的。另外我不鼓励使用md5()
,因为这个函数对于散列非常有用,但是如果你只使用它来生成字符,它会大大降低你的代码速度。
此外,您自己的代码建议会生成 4 个随机字符,可能是 0-9 或 af(十六进制),为您提供 16 种可能性。16 种可能性的 4 个字符为您提供 16x16x16x16 = 65,536 个唯一字符串。很有可能在渲染 10,000 个这些字符串时,您会得到重复项。
我建议您自己从字符 0-9、az 和 AZ 生成一个随机字符串,每个字符为您提供 36 种可能性,4 个字符为您提供 36x36x36x36 = 1,679,616 个唯一字符串。更多的字符可以减少重复(碰撞)的可能性。你可以这样做:
function randString($length = 4) {
$randChars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randString = '';
while (strlen($randString) < abs(intval($length))) {
$randString .= substr($randChars, rand(0, strlen($randChars)-1), 1);
}
return $randString;
}
$id = date('m') . randString(4);
我还会-
在月份和随机字符之间省略破折号(''),因为这样可以为您节省 1 个字符,并且您知道前两个字符将始终是月份的编号。
编辑:做了一些测试
我已经对碰撞进行了一些测试:我已经渲染了 10,000 个随机字符串一百次,并且每次都检查唯一性。使用长度 3、4(如您所做的)、5 和 6 完成此操作。结果如下:
-------- Length 3 ------------
Minimal duplicates: 170
Maximum duplicates: 241
Average duplicates: 207.05
-------- Length 4 ------------
Minimal duplicates: 0
Maximum duplicates: 8
Average duplicates: 3.19
-------- Length 5 ------------
Minimal duplicates: 0
Maximum duplicates: 2
Average duplicates: 0.05
-------- Length 6 ------------
Minimal duplicates: 0
Maximum duplicates: 0
Average duplicates: 0
正如Mark B在提到生日问题时也指出的那样,不能排除绝对 0% 的碰撞几率。