我目前做这样的事情,但我当前生成的ID是随机的,并且在循环中检查冲突是令人讨厌的,并且如果记录数量显着增加将变得昂贵.
通常担心碰撞不是问题,但我想要生成的唯一ID是一个短的唯一字符串5-8个字符,字母数字,就像tinyurl一样.
编辑:我想从5个字符开始,如果我达到6000万个条目,那么转到6 ..依此类推.
为此,我想我可以使用对用户隐藏的auto_increment值,而是使用MD5或其他方法显示它们以从中生成唯一的字符串.
生成的字符串看起来不应该是线性的,所以简单地将auto_incremented ID转换为base 36 [0-9A-Z]有点过于简单了,但是这样的函数就是我要用的东西.
编辑:安全性不是问题,因为这不会用于保护信息.它只是一个较长字符串的快捷方式.
谢谢.
感谢您的建议,抱歉延误.牙医..
一些例子(这些的任何组合也应该有效):
>反转一些位(f.i.使用XOR,^在PHP中)
>交换位数(($i& 0xc)>> 2 |($i& 0x3)<< 2),或者只是颠倒所有位的顺序
>添加一个常数值,以模拟你的最大范围(如果你把它与上面的那个结合起来,必须是两倍)
示例:此函数会将0,1,2,3,5,..转换为13,4,12,7,15,..,数字最多为15:
$i=($input+97) & 0xf; $result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;
编辑
一种更简单的方法是使用线性同余生成器(LCG,通常用于生成随机数),它由以下形式的公式定义:
X_n+1 = (a * X_n + c) mod m
对于a,c和m的good values,X_0,X_1 … X_m-1的序列将包含0和m-1之间的所有数字恰好一次.现在,您可以从线性增加的索引开始,并使用LCG序列中的下一个值作为“秘密”键.
EDIT2
执行:
你可以design your own LCG parameters,但如果你弄错了它将不会覆盖整个范围(因此有重复)所以我将使用this paper中已发布和尝试过的一组参数:
a = 16807,c = 0,m = 2147483647
这给你一个2 ** 31的范围.使用pack(),您可以将结果整数作为字符串,base64_encode()使其成为可读字符串(最多6个有效字符,每字节6位),这可能是您的函数:
substr(base64_encode(pack("l",(16807 * $index) % 2147483647)),6)