Page 1 of 1

Create a Random Number

Posted: Sat Jun 03, 2006 11:35 pm
by tecktalkcm0391
Can anybody tell me how to do this: I want to make a function that does this: Creates a Random Number, then checks in the database table users under code. If it finds the number it picks again, if not it updates their info to give them that number.

This is what I have so far

Code: Select all

<?php
function new_code() {

$cncodeand(1111111111, 999999999);
$query = @mysql_query("SELECT code FROM users");
$iccode=mysql_query($query);
if(!$iccode) {
	new_code();
	}

}
?>

Posted: Sun Jun 04, 2006 12:45 am
by bdlang
Something like this should work:
(untested example)

Code: Select all

/*
    function declaration:
    pass the username, rand string length, database link ( by reference )
*/
function createCode(&$dblink, $username, $length=999999) {

    // generates a random number between 0 and the length chosen
    $randnum= mt_rand(0, $length);

    // create SQL statement to check for the user's code, see if it matches
    $sql = 'SELECT COUNT(*) FROM `users`';
    $sql.=  " WHERE `username` = '{$username}' AND `code`= '{$randnum}'";
    // run the query, return the result, see if it exists
    $res= mysql_query($sql, $dblink);
    if ( mysql_result($res,0) == 1 ) {
        // recursive function call if it exists, try it all over again
        createCode($dblink, $username, $length);
    }
    else {
        // create SQL statement to update the user info
        $sql = "UPDATE `users` SET `code` = '{$randnum}'";
        $sql.= " WHERE `username` = '{$username}'";
        $res= mysql_query($sql, $dblink);
        // if the update was successful, return the data
        if ( mysql_affected_rows($dblink) == 1 ) {
            return $randnum;
        }
        else {
            // if not, return FALSE
            return (bool) FALSE;
        }
    }
}
example of usage:

Code: Select all

$conn= mysql_connect('foo','bar','foobar');
$db= mysql_select_db('test',$conn);

// pass the username in the GET string
$username= mysql_real_escape_string($_GET['u']);

// check and call the function
if ( $randnum= createCode($conn, $username) ) {
    echo 'Your information has been updated.<br />';
    echo 'Your new code is: ' .$randnum;
}
else {
    echo 'Update failed.<br />';
}

Posted: Sun Jun 04, 2006 9:20 pm
by tecktalkcm0391
Thanks!,but is there anyways to make the process of creating the random number keep going until it picks a number that hasn't been used before ?

Would something like a loop work ? If so, can someone give me an example?

Posted: Sun Jun 04, 2006 9:35 pm
by Christopher
I am wondering why you are trying to create a random number rather than just using an autoincrement field with will provide the next unique id in the sequence for each INSERT.

Posted: Sun Jun 04, 2006 10:18 pm
by tecktalkcm0391
Because this is only part of the code, what the rest is doing is adding 7 to the last user's code. But if for some reason they don't have a code, it creates a new one for them.

Posted: Sun Jun 04, 2006 10:23 pm
by bdlang
tecktalkcm0391 wrote:Thanks!,but is there anyways to make the process of creating the random number keep going until it picks a number that hasn't been used before ?

Would something like a loop work ? If so, can someone give me an example?
Hmm, good point, I was looking at it from the viewpoint of creating a password or specific code for a specific user, not necessarily creating a unique code overall. I suppose since people have the ability of choosing their own passwords most of the time, it is possible more than one user could have the same `code` value anyway. Best practice to get around this issue is to store each user code as a HASH and use a unique SALT on the hash, as mentioned in a previous post.

Change the initial query so that it doesn't use the `username` column at all, e.g.

Code: Select all

// create SQL statement to check for the user's code, see if it matches
 $sql = 'SELECT COUNT(*) FROM `users`';
$sql.=  " WHERE `code`= '{$randnum}'";

This way it looks up the entire set of records to see if the unique random value matches. If it does, a new number is generated, and so on and so forth until a completely unique value is found. The other way to go about this would be to use a UNIQUE index on that particular column, and if the INSERT failed due to a redundant field value, your logic could regenerate a new key, etc.

Posted: Sun Jun 04, 2006 10:25 pm
by bdlang
arborint wrote:I am wondering why you are trying to create a random number rather than just using an autoincrement field with will provide the next unique id in the sequence for each INSERT.
Good point, and there should be an auto-incremented PRIMARY KEY for each record. I think in this case, however, it's a unique code for some purpose, and obviously the other user's could simply guess at some other user's code, anywhere from 1 to N as long as there are at least N users in the system.

Posted: Sun Jun 04, 2006 10:37 pm
by tecktalkcm0391
How could I go about doing something link:
The other way to go about this would be to use a UNIQUE index on that particular column, and if the INSERT failed due to a redundant field value, your logic could regenerate a new key, etc.

Posted: Sun Jun 04, 2006 11:02 pm
by bdlang
tecktalkcm0391 wrote:How could I go about doing something link:
The other way to go about this would be to use a UNIQUE index on that particular column, and if the INSERT failed due to a redundant field value, your logic could regenerate a new key, etc.
Well, that's in your DB table design. You're using MySQL, so it's relatively easy to implement this. The only reason I didn't think of it before is (as I mentioned), I wasn't thinking in lines of creating an overall unique code, simply unique to the user (although it would very likely be both). Using a UNIQUE index is actually an easier practice, as in
(YAUE::yet another untested example)

Code: Select all

/*
    function declaration:
    pass the username, rand string length, database link ( by reference )
*/
function createCode(&$dblink, $username, $length=999999) {

    // generates a random number between 0 and the length chosen
    $randnum= mt_rand(0, $length);
    // query to update the user's `code` value
    $sql = "UPDATE `users` SET `code` = '{$randnum}'";
    $sql.= " WHERE `username` = '{$username}'";

    // the actual query call
    $res= mysql_query($sql, $dblink);

    // if mysql_affected_rows returns 1, we know it updated ok
    if ( mysql_affected_rows($dblink) != 1 ) {
        // the query failed, let's regenerate a code value
        createCode(&$dblink, &$username, &$length);
    }
    else {
        return $randnum;
    }
}

$conn= mysql_connect('foo','bar','foobar')
    OR die('CONN::<br />'.mysql_error());
$db= mysql_select_db('test',$conn)
    OR die('DB::<br />'.mysql_error());
$username= mysql_real_escape_string($_GET['u'],$conn);

$randnum= createCode($conn, $username);
echo "Your new unique code is: {$randnum}";
A much more simple implementation of the code, and all you need to do is create a UNIQUE index on that particular field, e.g.

Code: Select all

ALTER TABLE `users` ADD UNIQUE (`code`);
MySQL keeps a check on that column, it will not allow a non-unique value to be inserted into any record in the table.

Posted: Sun Jun 04, 2006 11:15 pm
by tecktalkcm0391
Ok, but how can I make incoorperate:
1.) if code is not in database give rand. code
2.) if code is in database try again, until it finds a code.

Posted: Sun Jun 04, 2006 11:25 pm
by bdlang
tecktalkcm0391 wrote:Ok, but how can I make incoorperate:
1.) if code is not in database give rand. code
2.) if code is in database try again, until it finds a code.
The code I've shown will do exactly that.
Here's what the function 'createCode()' does, step by step:
  • Generates a random code.
  • Attempts to perform an UPDATE on the user's code, whether the user currently has a code or not.
  • If the UPDATE query works, user has a new, random, completely unique code -> function exits with the value of the user's new random code (could also simply return TRUE or without a value at all, but it needs to exit somehow).
  • If the UPDATE query fails, the code exists already in some record in the table (that's what the UNIQUE index keeps tabs on) -> recursive call to the createCode() function starts the process over again.
  • Function eventually exits when it finds a random, unique value (which as I mentioned, may not even happen).

Posted: Sun Jun 04, 2006 11:26 pm
by tecktalkcm0391
sorry, i didn't relize that !

:( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry: :( :cry:

THANK YOU VERY MUCH!

Posted: Sun Jun 04, 2006 11:39 pm
by bdlang
:) NP.

One thing I realized as I was looking at the code again, that it will literally generate a random value between 0 and 999999 (or whatever value you pass in the $length parameter, as long as it isn't longer than mt_rand() can handle on your system), so you can wind up with values like

12
809765
3409

etc.

You'll probably want them to be consistent, so you might want to change the code so it doesn't bother to pass a $length parameter (or pass both a $start and $end parameter), instead do

Code: Select all

$randnum= mt_rand(111111, 999999);

// or in the case of two parameters
$randnum= mt_rand($start, $end);
You'll get a consistent value within that range. And I think that's enough values to match users on your system for awhile. ;)

Posted: Mon Jun 05, 2006 12:14 am
by tecktalkcm0391
...I think that's enough values to match users on your system for awhile.
Yeah, I think so too!, but you never know!

Thanks again!