php函数生成随机字符串连续返回重复值

I have written a function to generate a random string of 7 alphanumeric characters which I am then inserting in a mysql database.

Here is the code :

function getRandomID(){
   $tmp ="";
   $characters=array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9");
   for($i=0;$i<7;$i++) 
       $tmp.=$characters[rand(0,count($characters)-1)];
   return $tmp;
}

I am not checking for duplicates atm because I anticipate there will be no more than 1000 entries in the database and I've calculated that this function can return (35)^7 = 64,339,296,875 possible values.

I am testing it out locally as well as on a live server.

The problem is just in the last hour , this function generated duplicate values twice.

I came upon 3 entries in the database all of which had the same random string.

I do not know what could have caused this as I tried numerous times afterwards and the problem wasn't reproducible.

Does anybody have any idea what could be going on here?

Many thanks in advance

Designing your code with the mindset of "meh, that's not going to happen" is a very risky game, just do it properly once so you don't have to get back to your code multiple times to quick-fix minor things like these.

Do the duplicate check and you'll be solid.

You can create a function like

function stringExists($string)
{
     ...
    return $boolValue;
}

And you can easily create a while loop that generates a new string while an old one has been generated.

$duplicate = true;
while($duplicate)
{
    $newString = getRandomId();
    $duplicate = !stringExists($string);
}
// Work with the newest string that is not a duplicate.

If you really want to get into it

You can then take a look at the documentation for rand if you want to find out what might be causing your problem. Besides, 3 entries doesn't mean anything if we don't know how many total entries there are. Also sometimes "random" function are not as random as one might think, sometimes random functions in some programming languages are always usable but require some sort of an initiation before they become "truly" random.

The time of the inserts might also be a part of the problem, there are plenty of threads on the internet, like this one on stackoverflow, that have some interesting points that can affect your "random"ness.

Whether it's true or not, not which has been pointed out in the comment, you can be pretty sure to find an answer to your question in related threads and topics.

Short answer: Don't think about it and do a duplicate check, it's easy.

Note that you should, of-course, make your ID be a UNIQUE constraint in the database to begin with.

  1. Random != unique. Collisions happen. Check that the value is unique before you insert into the database, and/or put an integrity contstraint in your DB to enforce uniqueness.
  2. If you're using a very old version of PHP [eg. pre-4.2] you have to seed the random number generator with srand().
  3. Aside from #2, it's probably not your getRandomID() function but something else in your code that's re-using previous values.

If you need to enrer unique data in the DB, you may use PHP function uniqid(). (http://ca3.php.net/uniqid)

The function generates more-less random string based on current microseconds. So in theory it is unique.

But still, its always good to check before insert. Or at least put UNIQUE index on the field.

You could do something like this:

function randomString($length, $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {
    $string = "";
    $charsLength = strlen($chars);
    for ($i = 0; $i < intval($length); $i++) {
        $string .= $chars[rand(0, $charsLength - 1)];
    }
    return $string;
}

The function above will generate a random string in the given length from the given characters. This makes it a little bit more flexible, than your implementation, if you need to use it in amother context later.

Then you could do a check like this:

$id = null;
do {
    $id = randomString(7);
} while (!isUnique($id));

// do your insert here. You need to write your isUnique, so that it checks if
// the given string is unique or not.