自定义唯一ID

时间:2011-07-11 15:36:49

标签: php yii

有什么方法可以让我的模型ID(主键)生成随机唯一的8位数字,只包含数字而不是默认的自动增量? 客户要求这个特定的8位数字的功能,所以我不能争论原因。

我想使用PHP uniqid但它是13位数字并且还包含字母表。

有什么想法吗?

感谢。

更新

我忘了告诉我需要随机生成每个新记录的ID。

只想询问生成ID的机制,然后保存ID(也是属性)。我是否必须首先检查数据库中是否存在随机生成的ID是否已经存在另一个相同的密钥,然后保存属性还是什么?

4 个答案:

答案 0 :(得分:3)

为什么不保留自动增量但是将其设置为从主键上的10000000开始而不是1?

ALTER TABLE some_table AUTO_INCREMENT=10000000

答案 1 :(得分:1)

保留ID,但请填充它。

$id = 6;
$padded_id = sprintf("%013d", $id);
// This will print 0000000000006

这将填充$id,使其长达13位。

每当您需要显示ID时,请使用转换它的函数,就像这样。

function padId($id){
    return sprintf("%013d", $id);
}

或者您可以在表中创建一个名为pad-id的行,然后在创建记录时运行此函数(以及mysql_insert_id(以便刚刚插入ID))。

答案 2 :(得分:1)

是的,你可以。在谈论人工智能时,我假设你在使用MySQL。只是不要将其设置为自动增量,并插入其他列的值。您可以创建一个函数或方法,最多可以随机或按特定顺序(算法)获取8个数字。

INSERT INTO model (id, name, value, etc) VALUES (87654321, 'My selected name', 'some price or text', 'etc')

考虑INT(11)值可以接受从-2147483648到2147483647.这适合8位数的数字。如果稍后客户端请求更大的数字,您可能需要切换到BIGINT。

我用来将主键设置为无符号,这允许您拟合0到4294967295之间的数字。

对于php函数 - 8位数的生成器:

<?php

mt_srand();
$id = mt_rand(10000000, 99999999);

?>

您可以在php文档中阅读有关mt_srand()和mt_rand()的更多信息。据说它们比srand()和rand()更好。

答案 3 :(得分:1)

最好的方法取决于客户随机性要求的微妙方面 - 当他们说随机时,他们意味着完全不可预测或难以预测吗?我并不是说在Lewinski试验中听起来像克林顿,但是当客户说随机影响你是否有可能满足要求时,你的意图是什么。

如果客户想要隐藏用户ID(对于某些感知的安全性好处)并使它们几乎无法预测或反向工程,那么这非常困难。如果客户满意只是“难以”预测(我怀疑),那么你可以做一些简单的事情,类似于md5方法(@Dotty)。但是md5不是collision resistant。即使使用最好的,可证明唯一的哈希算法(md5不是),如果用户数量大于用户ID允许的位数(8),则会出现冲突问题。您有大约27位可以使用8位十进制数字。这意味着你可能会在2 ^ N / 2 = 2 ^(27/2)之后发生碰撞,大约是10K用户。因此,如果您的客户端的用户列表接近10K用户,那么即使是最好的哈希算法也会花费大量时间来过滤掉所有冲突。 要在没有过滤器和非确定性算法的情况下解决此问题,只需使用简单的“Full Cycle”算法。有些将产生伪随机数(PRN),这些伪随机数保证是唯一的,并保证完全跨越你想要覆盖的任何范围(例如,所有8位正整数的集合)。如果您需要对用户注册序列进行反向工程,只需使用您使用的任何初始值重新运行完整周期PRN生成器。如果您的客户希望让黑客对您的用户ID序列进行逆向工程,那么您可以将这个初始值保密,就像私钥一样。

您的客户的另一个问题是用户ID是否允许前导零。如果是这样,(并且客户端的随机性要求是自由的)那么维基百科上的简单Full Cycle算法将很适合您。它可以被提炼为2行PHP。 无论你使用什么算法,在一个单独的表中实际生成官方8位半随机用户ID列表,然后只要你弹出“表”顶部的值(删除那一行)就可能了。添加新用户。数据库内存要求不应过高,它将简化用户体验,消除由复杂的,不确定的随机数生成器和唯一性过滤器引起的任何延迟和内存吞噬。试图在线创建用户ID,实际上,可以想象你可以通过一些哈希算法无限期地停止用户注册进入永久循环。并且这个失速(由于永久碰撞)可能不会发生,直到用户1000或10000.相反,使用离线查找表方法,您可以轻松添加其他客户端规定的过滤器,如消除带前导零的ID;如果客户端永远不想看到ID为1的用户(00000001)。而且你事先知道一切是否会一直有效,没有任何问题。