Php 如何生成一个不再相同(重复)的数字

Php 如何生成一个不再相同(重复)的数字,php,codeigniter,numbers,Php,Codeigniter,Numbers,可能重复: 是否可以生成一个永远不会重复的随机数 php中有解决方案吗?还是密码点火器 例如,如果我需要为每个用户生成一个随机的从不重复的id,如何确保没有用户具有相同的id?使用以下方法:http://php.net/manual/en/function.uniqid.php <?php /* A uniqid, like: 4b3403665fea6 */ printf("uniqid(): %s\r\n", uniqid()); /* We can also prefix the

可能重复:

是否可以生成一个永远不会重复的随机数

php中有解决方案吗?还是密码点火器


例如,如果我需要为每个用户生成一个随机的从不重复的id,如何确保没有用户具有相同的id?

使用以下方法:http://php.net/manual/en/function.uniqid.php

<?php
/* A uniqid, like: 4b3403665fea6 */
printf("uniqid(): %s\r\n", uniqid());

/* We can also prefix the uniqid, this the same as 
 * doing:
 *
 * $uniqid = $prefix . uniqid();
 * $uniqid = uniqid($prefix);
 */
printf("uniqid('php_'): %s\r\n", uniqid('php_'));

/* We can also activate the more_entropy parameter, which is 
 * required on some systems, like Cygwin. This makes uniqid()
 * produce a value like: 4b340550242239.64159797
 */
printf("uniqid('', true): %s\r\n", uniqid('', true));
?>

您需要这些数字中的多少?如果您需要无限数量的唯一号码,您可能还需要无限空间来存储此类号码

如果您只想要一个特定范围内的数字,比如说0到20亿,您可以通过存储整个范围并将其洗牌来确保每个数字只使用一次。然后,每次需要一个数字时,增加上次用于获取下一个数字的索引。当达到最高索引时,生成一个新的范围,或者只是重复使用相同的范围

对于20亿个数字,此解决方案只需花费8GB的数据,保证彼此之间的唯一性

但是,正如你所想象的,通常有更好的解决方案,也许你可以使用一个不那么唯一的数字、一个时间戳,甚至只是一个递增计数器

如果将用户存储在数据库中,则可以使数据库为您生成唯一的用户ID。这将是一个不断递增的整数。如果您使用一个自动递增的int字段,您不会很快达到userid的限制

如何确保没有用户具有相同的id


检查是否有用户已经有了它?

您的问题的简单答案是明确的否。如果必须是完全随机的,它将永远不会是唯一的100%概率

您可以生成长而复杂的随机标记,并承担一点非唯一性风险,也可以在生成后检查数据库中的唯一性


但正如其他人所指出的,你很可能只是要求解决一个已经解决的问题。这意味着您应该在数据库表中使用自动递增的主索引,以确保记录的唯一性。

显然,总有可能出现一个数字,因为每个表单通常由相同的算法生成

最安全的方法是检查您的数据库,以确保在已获取id的情况下:

$id = "1"; //Your id to check
$query = "SELECT * FROM table where id=?";
$result = mysql_query($query);
if(mysql_num_rows($result)) { 
  //the id is present
}
如果改用mysqli,效果会更好

$id = "1"; //Your id to check
$query = "SELECT * FROM table where id=?";
$stmt = mysqli_prepare($link, $query);
mysqli_stmt_bind_param($stmt, "i", $id);
mysql_stmt_execute($stmt);
if(mysql_stmt_num_rows($stmt))
  //the id is present
}  
mysqli_stmt_close($stmt);

要使某些内容具有唯一性,您基本上需要一个唯一的字符串,该字符串的开头可能是来自数据库的自动递增值,甚至是
microtime(true)
, 如果您使用用户名或电子邮件之类的东西检查唯一性,那么如果您没有来自数据库的自动递增值,则可以使用该值

下面是一个快速的usless函数,它将字符串扩展为更唯一的值sha1,然后获取sha1字符串的crc校验和。并将其填充到最大长度 这有点过分了,因为你可以用000001000002来填充这个值,但其中的乐趣在哪里呢

<?php 
function make_user_id($id,$lenth=10){
    return str_pad(substr(sprintf("%u", crc32(sha1($id))),0,$lenth), $lenth, "0", STR_PAD_LEFT);
}

//mysql_insert_id() or something unique from user, pahaps an email address or name
//example
foreach(range(1,25) as $id){
    $array[]=make_user_id($id,10);
}
sort($array);

print_r($array);
/*
Array
(
    [0] => 0299258281
    [1] => 0361369892
    [2] => 0391093287
    [3] => 0422444891
    [4] => 0492247561
    [5] => 0642853861
    [6] => 0737524653
    [7] => 0860628658
    [8] => 0944014851
    [9] => 1054358011
    [10] => 1065666469
    [11] => 1194536188
    [12] => 1390882148
    [13] => 1617647885
    [14] => 1648921238
    [15] => 2611355852
    [16] => 2612669788
    [17] => 2615382585
    [18] => 3526511484
    [19] => 3578384747
    [20] => 3888148475
    [21] => 4095122425
    [22] => 4197940240
    [23] => 4288076077
    [24] => 4293497861
)*/
?>

这将生成一个带有数字和字母的随机字符串(我使用它作为密码)。
请从中阅读,它很有用。

您确定它必须是随机的吗?递增ID是否不合适?另一件需要注意的事情是,数据库可以为您创建一个唯一的ID,如果它是用户ID,这可能是解决方案。您在数据库中使用自动递增的primarykey,就是这样。是的,这样想,我将不得不讨论它,因为这不是我的想法:)只使用用户名作为唯一标识符合适吗?当然,您不会有两个用户使用相同的用户名。uniqid不仅有一个非常糟糕的名称,而且不能保证它是唯一的。实际上,它有一个参数可以设置为“true”以使其“更可能是唯一的”。这样的数字永远不能保证是唯一的。感谢您的建议,现在我使用的是rand(1000000)+user_id+其他,也许这是个坏主意,我将尝试使用此函数代码使用mysql API,这应该被视为不推荐使用。@markus tharkun,你确定它们已被弃用吗?它们“不是”,但“应该”去润滑。使用事先准备好的陈述。-1:这不是你使用事先准备好的陈述的方式。您的代码仍然可以进行SQL注入。@Starx:
mysqli\u prepare(“从id='$id'的表中选择*)
容易进行SQL注入。通过这样准备你的陈述,你基本上否定了准备陈述的优点:1。您的查询计划将仅编译为一个可能的结果(即:您的查询不可重用),2。您没有使用绑定参数,因此容易受到SQL注入攻击。也许您是对的,但我正在尝试避免更多SQL查询您想避免SQL查询这种自然现象的任何原因?尽管这个答案非常完美,但我可以理解,一旦有了大量用户,您为什么要避免额外的查询。从理论上讲,你可能会得到类似
A;如果{generate_other;goto A;}
这取决于你生成数字的方法,它可能永远持续下去(也就是说,如果你不聪明的话)。
bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM))