tags:

views:

422

answers:

4

hello i'm using PHP , Mysql i have a table with 3 fields (( ID , Username , PID )).

i want 'PID field' to contain string of 8 unique chars.

my solution is to generate the random string in PHP and check if it's exists if it's exists then it will generate another string .

is there any better solution that will save processing time like mysql trigger or sth like that?

A: 

Do the characters need to be random? Or just unique? If they only need to be unique, you could use a timestamp. Basing the value on time will ensure a uniqueness.

If you go another route, you'll have to check your generated value against the database until you end up with a unique value.

Jonathan Sampson
Be careful: with MySQL's timestamps if two records are added within a second of each other they may have the same timestamp.
Alex Reisner
Alex, base it on the milliseconds if at all possible.
Jonathan Sampson
A: 

This will give you a random 8 character string:

substr(str_pad(dechex(mt_rand()), 8, '0', STR_PAD_LEFT), -8);

Found here: http://www.richardlord.net/blog/php-password-security

Or if the username field is unique you could also use:

substr(md5('username value'), 0, 8);

Though it's extremely unlikely, particularly for the md5, neither case guarantees a unique string, so I would probably do something like this:

// Handle user registration or whatever...

function generatePID($sUsername) {
    return substr(md5($sUsername), 0, 8);
}

$bUnique = false;
$iAttempts = 0;

while (!$bUnique && $iAttempts < 10) {
    $aCheck = $oDB->findByPID(generatePID("username value")); // Query the database for a PID matching whats generated
    if (!$aCheck) { // If nothing is found, exit the loop
        $bUnique = true;
    } else {
        $iAttempts++;
    }
}

// Save PID and such...

... which would probably only yield 1 'check' query, maybe 2 in unique cases, and would ensure a unique string.

Chris Forrette
so the best way to do it to generate one in php and loop through the database to check if it's exist .i thought i could find a way that will do that in some magin mysql statement
From.ME.to.YOU
Not that I'm aware of. You should also have a UNIQUE key on your PID field, which will fail on an attempt to insert a non-unique value, which gives you another option to run a loop to keep trying until something gets successfully inserted. I see you're doing an image gallery and we actually always store an md5 of the current time + file name and then pop on the file extension into a 'file' field for that, which always gets us a unique string -- we've never had an issue in about 8 years. The field needs to allow for 32 characters + the extension length though -- we usually just stick with 50.
Chris Forrette
A: 

Why not do this the correct way and use UUIDs (aka GUIDs), which are always unique, no need to check if they are or not. It may be 36 chars, but you get the benefit of storing them as HEX which saves disk space and increase speed over standard CHAR data.

You can read the comments on the PHP doc for functions that do this.

TravisO
A: 

If you're set on 8 characters for the PID value then you'll need something to generate the string and check that it doesn't already exist.

$alphabet = range('A','Z');

// get all the PIDs from the database
$sql = "select PID from mytable";

// save those all to an array
$pid_array = results of query saved to array

shuffle($alphabet);
$pid_offer = array_slice($alphabet,0,8);

while(in_array($pid_offer, $pid_array)){
    shuffle($alphabet);
    $pid_offer = array_slice($alphabet,0,8);
}

// found uniuqe $pid_offer...

race conditions still exist.

If the string doesn't need to be random, then use the ID value, which is probably an auto-increment integer and start the count for that at 10000000.

Then just do a simple A=1, B=2, C=3 etc replacement on the digits in that number to generate your string.

Your mileage may vary.

--Mark

Mark Moline
ya it need to be random. thanks for your solution but could it be done in a mysql trigger ? or sth like that ? that would save processing time ? or not ?
From.ME.to.YOU
ok, so the code solution above gives the randomness you're looking for. To avoid the race condition you could store the file with an md5(microtime(true) . $origfilename). Then have a separate cron process that chugs through the new images directory to give them their proper filename, updates the database with the PID value, and notifies the user that their image(s) are processed and ready for viewing.Just a thought.
Mark Moline
You should also develop a list of strings that should not be allowed in the PID value. Obscenities and such. Then filter the $pid_offer value against that list before inserting. There's a lot of really improper words that can be spelled in 8 or fewer characters!
Mark Moline