tags:

views:

60

answers:

5

I want to generate a random string of about 5 characters long. I can create it ok, but I'm having trouble checking if it exists in an array (or database in real situation) and creating a new one if it does.

I use a function like this to generate the string:

function rand_string(){
    return substr(md5(microtime()), 0, 5);
}

But them I'm lost.

  • I need to check if it exists already.
  • If it does, make a new one
  • And repeat
+3  A: 

Try this:

function rand_string(){
    $str = substr(md5(microtime()), 0, 5);
    if(exists_in_db($str)) $str = rand_string();
    return $str;
}
Jacob Relkin
if that method fails often you could run into serious troubles cause of calling-depth...a while would be better!function rand_string(){ $str = ""; do { $str = substr(md5(microtime()), 0, 5); } while(exists_in_db($str)); return $str;}hope that is a valid do{}while() construct in php
santa
what i mean every function call pushes on the stack... you could segfault if the calling-structure gets to deep...
santa
The chances of this happening are very very slim.
Jacob Relkin
Yeah but frankly before microtime+md5 causes a collision it couuld be ages.
Iznogood
It wouldn't be a segfault. It would be a stack overflow... And with a 5 character id, that's quite possible (16 possible characters, 5 places, that's only about 1 million unique codes)... So in this particular case, I'd agree about the while. If you used a longer identifier (where there were trillions or more unique codes), I'd say it's a rare edge case for deep recursion...
ircmaxell
+1 for using "Stack Overflow" in a sentence.
NinjaCat
For more info why collisions are very likely, see http://en.wikipedia.org/wiki/Birthday_attack For a 5 char id, you'd have a 50% chance of each new id being a collision with only about 1000 rows in the db. And not many more for a 75% chance of collision, under around 2000 rows...
ircmaxell
A: 

on a database you could..:

select substr(newid(),1,5) as name

for a new string and to check..:

select count(*) as cnt from yourtable where yourcolumn = __GENERATED_string__

build a while around it and you'Re done

santa
A: 

With the mysql_query(), use a select statement to see if you return any results (i.e., "Select * from table where col1 = 'String'". Then test to see if any rows were returned. Loop through these calls until you have a truly random, unused value.

websch01ar
+1  A: 

To check if it's in the DB run a query after.

$unique=FALSE;
    while(!$unique)
      {
      $str = substr(md5(microtime()), 0, 5);
      //Insert SQL Code to check if used here
      if($row['ID']=='')
          $unique=TRUE;
      }
ari_aaron
this type of loop is typically done with a `do while` loop as there is always at least one iteration.
Progman
@progman: that's what i intended with my comment @jacob...you can drop the bool that way...and you have no recursion which is quite unsafe after a few iterations
santa
+2  A: 

Just a warning that if you are using this to generate a unique string by adding it to the database once you've determined it's not been used then this is not safe in a concurrent environment.

In the interval between you checking it's not in the database, and adding a record containing it later on another thread could do the same...

If you are using it this way, probably the safest approach is to ensure that the field containing the string has a unique constraint on it and try to add it. If you suceeded in adding it then you know it was unique, if you didn't then it wasn't. And this is safe to do in a multithreaded environment.

If you are simply checking against a static list of strings and do not intend to add the generated string to the database then ignore this post :P

John Burton