1

I would like to create a random ID like an airline ticket with out any zeros, o's, ones's, or L's. It would be nice if server time was used in the generation process so no two IDs will be the same. How would one do this?

k to the z
  • 3,217
  • 2
  • 27
  • 41

5 Answers5

8

Following the awesome PHP naming scheme:

function generate_airline_ticket_number($length) {
  $characters = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ';
  $max = strlen($characters) - 1;
  $string = '';

  for ($i = 0; $i < $length; $i++) {
    $string .= $characters[mt_rand(0, $max)];
  }

  return $string;
}

I should submit this to be included into PHP6 ;)


If you're worried about collisions, my approach would be to do an endless loop:

do
{
  $random_stuff = generate_airline_ticket_number(10);
} while(check_if_string__is_not_in__the_database($random_stuff));
Blender
  • 289,723
  • 53
  • 439
  • 496
  • +1 for the comment about naming scheme. Only submit it to PHP 6 if for PHP 6.5 you decide to reverse the order of some of your parameters. :-D – Brad Apr 14 '11 at 18:48
  • @k to the z, use this function but be sure to store the result in a DB somewhere so you know that a collision can't occur. – Brad Apr 14 '11 at 18:49
  • Seed this with your actual ID plus some static numerics and you'll always have a known random string. http://us.php.net/manual/en/function.mt-srand.php – Zimzat Apr 14 '11 at 18:50
  • @Brad, thanks for the eureka moment. Check the database, if there is a matching id then generate again. Duh. :) – k to the z Apr 14 '11 at 18:51
  • This will generate a notice: `Uninitialized string offset`. A simple fix would be to change `strlen($characters)` to `(strlen($characters) - 1)` – David Hancock Apr 14 '11 at 18:57
  • This function still doesn't prevent i's, 1's, o's, and zeros from being used. – k to the z Apr 14 '11 at 18:57
  • If you're really worried about a collision, you'd have to loop over the database, checking if your generated string is in there already. But realistically, if your string is 20 characters long, you'd need `20^57`, so you'd expect a collision of your database contained around `144 trevigintillion, 115 duovigintillion, 188 unvigintillion, 75 vigintillion, 855 novemdecillion, 872 octodecillion` entries (thanks Wolfram|Alpha). – Blender Apr 14 '11 at 18:58
  • Okay, I've updated the code. With the new code, expect a collision with a database containing `18 duovigintillion, 14 unvigintillion, 398 vigintillion, 509 novemdecillion, 481 octodecillion, 984 septendecillion` entries. – Blender Apr 14 '11 at 19:00
  • I just realized I needed to take out the charecters in the string and it generates exactly what I want. Thanks guys. – k to the z Apr 14 '11 at 19:01
  • You're welcome. The function works for any string input, so just tweak it to your needs. – Blender Apr 14 '11 at 19:01
  • Also, I'd take the `strlen()` call out of the loop if speed is an issue. Just do `$max = (strlen($characters) - 1);` above the loop and pass `$max` as the second argument to `mt_rand()` – David Hancock Apr 14 '11 at 19:03
  • Thanks, I've added that in. PHP isn't a speedy language in the first place, so optimizations would help. – Blender Apr 14 '11 at 19:04
0

There is always possibility that generated number will be repeated.

You have to store that generated earlier numbers and always check if currently generated number does not exist.

To generate a random number you can just use int rand ( int $min , int $max )

hsz
  • 148,279
  • 62
  • 259
  • 315
0

uniqid() seems perfect, apart from your limitations on letters and numbers. Selecting a great font may mitigate some of your needs, so you have L, a zero with a strike through, etc.

Baring that, you haven't placed any other limitations so what about.

$id  = uniqid()
$bad = array("0", "o", "l", "1");
$good = array("-", "#", "&", "$");

$id_clean = str_replace($bad, $good, $id);

The power of uniqid() combined with easily identified characters.

preinheimer
  • 3,712
  • 20
  • 34
0

Another option

function genGoodRandString() {
    $rnd_id = md5(uniqid(rand(), true)); // get long random id
    $bad = array('0','o','1','l','8'); // define bad chars
    $fixed = str_replace($bad, '', $rnd_id); // fix
    return substr($fixed, 0, 10); // cut to required length
}
J.C. Inacio
  • 4,442
  • 2
  • 22
  • 25
-2

Why not just use a hash like MD5? I believe PHP has a md5() function built in. Another good one to use is sha1().

Using both of these hash functions you will end up getting what you don't want so I suggest you run a regex pattern on the hash to replace them with a random letter A-Z.

Oh, and hashes are usually 100% unique.

I guess I learned something new today.

zamN
  • 236
  • 2
  • 7
  • 16
  • This is fine for basic use, but collisions can and will occur. Hashes are definitely *not* 100% unique. If they were, we could just use hash instead of the actual data. – Brad Apr 14 '11 at 18:45
  • 1
    NOOOO! If hashes are unique, then they are bijective, which means that the input can be calculated from the output. That point of hashes it to be *non-bijective*!!! – Blender Apr 14 '11 at 18:46
  • The database will have millions of records so this is a concern. – k to the z Apr 14 '11 at 18:46
  • See the second part of my response here: http://stackoverflow.com/questions/5655380/which-algorithm-for-hashing-name-firstname-and-birth-date-of-a-person/5655473#5655473. – Blender Apr 14 '11 at 18:48
  • The chance of a natural collision is so small, you can just ignore it. A *forced* collision, on the other hand, can happen quite quickly. If nobody's trying to mess with your database, hashing is a perfectly valid approach. – Blender Apr 14 '11 at 18:49
  • Ah, my mistake. @Brad. I wasn't thinking about that. >_ – zamN Apr 14 '11 at 18:57