-3

Possible Duplicate:
Algorithm for generating a random number

is posible to generate a random number that is never repeated??

Is there a solution in php? or codeIgniter?

for example if i need to generate a random never repeated id for every user, how can i be sure that no user will have the same id?

Community
  • 1
  • 1
yeah its me
  • 1,131
  • 4
  • 18
  • 27

7 Answers7

3

Use this :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));
?>
nycynik
  • 7,371
  • 8
  • 62
  • 87
  • uniqid not only has a terrible, terrible name, but it is not guaranteed to be unique. It actually has a parameter that can be set to 'true' to make it 'more likely to be unique'. – GolezTrol Mar 31 '12 at 14:23
  • Such a number is NEVER guaranteed to be unique. – markus Mar 31 '12 at 14:32
  • thanks for advice, by now i am using a rand(1, 1000000) + user_id + something more, maybe its a bad idea,i will try to use this function – yeah its me Mar 31 '12 at 14:39
2

How many of those numbers do you need? If you need an unlimited number of unique numbers, you may also need unlimited space to store such a number.

If you only want number in a specific range, say 0 to 2 billion, you could make sure you use each of these numbers exactly once, by storing the whole range and shuffle it. Then, each time you need a number, increment the index you last used to get the next number. When you reached the highest index, generate a new range, or just reuse the same range.

This solution will only cost you 8GB of data for 2 billion numbers, quaranteed to be unique amongs each other.

But, as you can imagine, there are often better solutions, and maybe you can live with a less unique number, a timestamp, or even just an incrementing counter.

If you're storing users in a database, you can make the database generate a unique userid for you. This will be an ever incrementing integer number. You won't hit the limit on userid's soon if you user an auto_increment int field.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
1

how can i be sure that no user will have the same id?

Check if some user already have it?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • maybe you are right, but i am trying to avoid more sql queries – yeah its me Mar 31 '12 at 14:37
  • 1
    any reason you want to avoid such a natural thing as SQL query? – Your Common Sense Mar 31 '12 at 14:41
  • As hilariously perfect as this answer is, I can understand why you'd want to avoid extra queries once you have lots of users. You could (theoretically) end up with something like `A; if(is_taken){generate_another; goto A;}` which depending on your method of generating the numbers, could go on forever (that is, if you aren't smart about it). – Wesley Murch Mar 31 '12 at 17:10
1

The simple answer to your question is a clear NO. If it has to be completely random it will never be unique in terms of 100% probability.

You can either generate long, complex random tokens and take a small risk of non-uniqueness or you have to check for uniqueness in a database after generation.

But as others noted, you're most probably just asking for the solution of an already solved problem. Meaning you should use auto incremented primary indices in your database tables to ensure unique records.

markus
  • 40,136
  • 23
  • 97
  • 142
1

To make something unique you essentially need a unique string to start with perhaps an auto incrementing value thats from a database or even microtime(true), perhaps if you make checks on uniqueness with something like username or email then use that if you don't have an auto incrementing value coming from the db.

Here is a quick usless function that will expand the string into a more unique value sha1 then get the crc checksum of the sha1 string. and pad it to a max len Its more then abit overkill as you could just pad the value with 000001,000002 but where the fun in that.

<?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
)*/
?>
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
0

Clearly speaking, there is always a chance for a number since every form is generated from same algorithm generally.

The safest way would be to check you database to ensure that, if an id is already taken like:

$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
}

It will be better if you use mysqli instead

$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);
Starx
  • 77,474
  • 47
  • 185
  • 261
  • Code uses mysql API which should be considered deprecated. – markus Mar 31 '12 at 14:36
  • @markus-tharkun, are you sure they are deprecated? – Starx Mar 31 '12 at 14:40
  • They 'are' not, but 'should be' depricated. Use prepared statements. – GolezTrol Mar 31 '12 at 15:52
  • @GolezTrol, Why dont you include an example on your post? I will update mine to mysqli instead – Starx Mar 31 '12 at 15:55
  • As I said, it is very much adviced that everybody consider the API deprecated and move on to PDO or mysqli. – markus Mar 31 '12 at 17:18
  • @Starx I figured my answer was more theoretical, but I'll consider. – GolezTrol Mar 31 '12 at 18:34
  • 2
    -1: That is **NOT** how you use prepared statements. Your code is still wide open to SQL Injections. – Andrew Moore Apr 01 '12 at 03:19
  • @AndrewMoore, Really, But no you are wrong, apart from the point your made, that is also a way to prepare the statement. I updated with `bind_param()` if that is what you are after – Starx Apr 01 '12 at 04:38
  • 1
    @Starx: `mysqli_prepare("SELECT * FROM table where id='$id'")` is prone to SQL injection. By preparing your statement like that you essentially negated to advantages of prepared statements: 1. Your query plan with will compiled with only one possible outcome (ie.: your query isn't reusable), 2. You are not using bound parameters and therefore prone to SQL injection attacks. – Andrew Moore Apr 01 '12 at 14:20
0
bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM))

that will generate a random string with numbers and letters(I use it for password salts). From http://crackstation.net/hashing-security.html please read it is helpful.