php中的短唯一ID

Ant*_*tti 47 php uniqueidentifier unique-index

我想创建一个独特的ID但是uniqid()给出类似的东西'492607b0ee414'.我想要的是类似于tinyurl给出的东西:'64k8ra'.越短越好.唯一的要求是它不应该有明显的顺序,它应该看起来比看似随机的数字序列更漂亮.字母比数字更受欢迎,理想情况下不会是混合字母.由于参赛人数不会那么多(最多10000人左右),因此碰撞的风险并不是一个很大的因素.

任何建议赞赏.

lpf*_*eau 43

创建一个小函数,返回给定长度的随机字母:

<?php
function generate_random_letters($length) {
    $random = '';
    for ($i = 0; $i < $length; $i++) {
        $random .= chr(rand(ord('a'), ord('z')));
    }
    return $random;
}
Run Code Online (Sandbox Code Playgroud)

然后你会想要在伪代码中调用它,直到它是唯一的,具体取决于你存储信息的位置:

do {
    $unique = generate_random_letters(6);
} while (is_in_table($unique));
add_to_table($unique);
Run Code Online (Sandbox Code Playgroud)

您可能还想确保字母不会在字典中形成单词.可能是整个英语词典或只是一个坏词词典,以避免客户会发现不良品味的东西.

编辑:如果你打算使用它,那么我也会添加这个只是有意义的,它不适用于大量的项目,因为你得到的冲突越多(在表中已经获得一个ID),这可能会变慢.当然,您需要一个索引表,并且您需要调整ID中的字母数以避免冲突.在这种情况下,使用6个字母,您将拥有26 ^ 6 = 308915776个可能的唯一ID(减去坏词),这足以满足您的需要10000.

编辑:如果您想要字母和数字的组合,您可以使用以下代码:

$random .= rand(0, 1) ? rand(0, 9) : chr(rand(ord('a'), ord('z')));
Run Code Online (Sandbox Code Playgroud)

  • 你应该把`ord('a')`和`ord('z')`放在循环之外,以避免在每次传递时调用函数. (2认同)

Cor*_*ott 28

@gen_uuid()来自gord.

preg_replace遇到了一些讨厌的utf-8问题,导致uid somtimes包含"+"或"/".要解决这个问题,你必须明确地将模式设为utf-8

function gen_uuid($len=8) {

    $hex = md5("yourSaltHere" . uniqid("", true));

    $pack = pack('H*', $hex);
    $tmp =  base64_encode($pack);

    $uid = preg_replace("#(*UTF8)[^A-Za-z0-9]#", "", $tmp);

    $len = max(4, min(128, $len));

    while (strlen($uid) < $len)
        $uid .= gen_uuid(22);

    return substr($uid, 0, $len);
}
Run Code Online (Sandbox Code Playgroud)

我花了很长时间才发现这一点,也许这让别人感到头疼


小智 25

您可以用更少的代码实现这一目标:

function gen_uid($l=10){
    return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyz"), 0, $l);
}
Run Code Online (Sandbox Code Playgroud)

结果(例子):

  • cjnp56brdy
  • 9d5uv84zfa
  • ih162lryez
  • ri4ocf6tkj
  • xj04s83egi

  • 很好的解决方案,但每个字母只能返回1次,这限制了可能性.我稍微重写了一遍:`function gen_uid($ l = 10){$ str =""; for($ x = 0; $ x <$ l; $ x ++)$ str.= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyz"),0,1); return $ str; }` (8认同)

Chr*_*ris 17

有两种方法可以获得可靠的唯一ID:使它变得如此长且可变,以至于碰撞的可能性非常小(与GUID一样)或将所有生成的ID存储在表中以供查找(在内存或数据库中)或文件)以验证生成时的唯一性.

如果您真的问如何生成这样一个短密钥并保证其独特性而不需要进行某种重复检查,答案是,您不能.


gor*_*ord 11

这是我用于任意长度的随机base62s的例程......

调用gen_uuid()返回字符串等WJX0u0jV, E9EMaZ3P.

默认情况下,它返回8位数,因此空间为64 ^ 8或大约10 ^ 14,这通常足以使碰撞非常罕见.

对于更大或更小的字符串,根据需要传入$ len.没有限制长度,因为我追加到[满足128个字符的安全限制,可以删除].

注意,使用随机盐的MD5 [或SHA1如果你喜欢],所以它不能很容易被逆向工程.

我没有在网上找到任何可靠的base62转换,因此这种从base64结果中剥离字符的方法.

在BSD许可下自由使用,享受,

胃食道逆流

function gen_uuid($len=8)
{
    $hex = md5("your_random_salt_here_31415" . uniqid("", true));

    $pack = pack('H*', $hex);

    $uid = base64_encode($pack);        // max 22 chars

    $uid = ereg_replace("[^A-Za-z0-9]", "", $uid);    // mixed case
    //$uid = ereg_replace("[^A-Z0-9]", "", strtoupper($uid));    // uppercase only

    if ($len<4)
        $len=4;
    if ($len>128)
        $len=128;                       // prevent silliness, can remove

    while (strlen($uid)<$len)
        $uid = $uid . gen_uuid(22);     // append until length achieved

    return substr($uid, 0, $len);
}
Run Code Online (Sandbox Code Playgroud)


小智 11

非常简单的解决方案:

使用以下内容创建唯一ID:

$id = 100;
base_convert($id, 10, 36);
Run Code Online (Sandbox Code Playgroud)

再次获取原始值:

intval($str,36);
Run Code Online (Sandbox Code Playgroud)

不能因为它来自另一个堆栈溢出页面而受到赞誉,但我认为该解决方案非常优雅且令人敬畏,因此值得复制到此线程以供引用此功能的人使用.


OIS*_*OIS 6

如果您想来回转换,您可以使用 Id 并将其转换为 base-36 数字。可用于任何具有整数 ID 的表。

function toUId($baseId, $multiplier = 1) {
    return base_convert($baseId * $multiplier, 10, 36);
}
function fromUId($uid, $multiplier = 1) {
    return (int) base_convert($uid, 36, 10) / $multiplier;
}

echo toUId(10000, 11111);
1u5h0w
echo fromUId('1u5h0w', 11111);
10000
Run Code Online (Sandbox Code Playgroud)

聪明的人可能可以通过足够的 id 示例来弄清楚。不要让这种默默无闻取代安全性。