Random String/Code Generator
This was a function written by a friend of mine for the CMS we work on.
I hope it can be useful to somebody.
/**
* Generates a random code
*
* @version 2.0
* @since 0.6.0
*
* @param int $maxLength
*
* @return string
*/
function randCode($maxLength=6){
$password = NULL;
$possible = 'bcdfghjkmnrstvwxyz123456789';
$i = 0;
while(($i < $maxLength) && (strlen($possible) > 0)){ $i++;
$character = substr($possible, mt_rand(0, strlen($possible)-1), 1);
$password .= $character;
}
return $password;
}
Written by Richard Clifford
Related protips
7 Responses
I made something similar a few days ago, with the added feature of generating strings with a high tendency to include more common characters.
function generate_string($length = 7, $variance = 5, $weight = 3) {
$length += rand(0 - $variance, $variance);
$l0 = str_split('tashwiobmfcldpnegryuvjkqxz');
$l = str_split('etaoinshrdlcumwfgypbvkjxqz.');
$str = '';
for ($i = 0; $i < $length; $i++) {
$a = $i == 0 ? $l0 : $l;
$s = count($a);
for ($r = 1; $r < $weight; $r++) {
$s = min(count($a) - 1, rand(0, $s));
}
$str .= $a[$s];
}
return $str;
}
It's used for generating test data so the code is fairly shoddy (especially variable naming), but the output is solid.
@richthegeek Seems like we have a very similar function all in all. Even the purpose. I used mine to create test data as well as session IDs for my Session Class which was then MD5'd (+ salt).
I would be interested in the performance output of each to be honest. I might do a test on them and get back to you.
@richthegeek Okay, I've done a bench mark on the two functions and mine is marginally faster than yours (tried to make the test as even as possible).
However, yours does seem to be a more thought out function which would return a better result.
------- Bench for generate_string() ------
0.84907793998718
------- </of> Bench for generate_string() ------
------- Bench for randCode() ------
0.33225393295288
------- </of> Bench for randCode() ------
Result : http://codepad.org/IQJSuY7A
Mine has the inner loop for weighting towards the start of the range - this could be done more efficiently (and more tunable) with logs or similar, but really any weighting will introduce a cost.
Ultimately, for test data, "human-ness" is pretty unimportant. And if you want to get it looking even close to reasonable, you need to use markov chains.
Something like the following provides a good weighted value, which can be modified by changing 2 to something larger/smaller (within reason).
$char = $len - round(log(pow(rand(0,$len),2))*$len*(1/2))
That would almost definitely be faster, even with the log.
Improved version that still has the weighting towards the start:
function generate_string($length = 6, $variance = 3, $weight = 2) {
$length += rand(0 - $variance, $variance);
$l0 = str_split('tashwiobmfcldpnegryuvjkqxz');
$l = str_split('etaoinshrdlcumwfgypbvkjxqz.');
$str = '';
for ($i = 0; $i < $length; $i++) {
$a = $i == 0 ? $l0 : $l;
$len = count($a) - 1;
$s = ceil($len - ($len * log(rand(0, $len), $len)));
$str .= $a[$s];
}
return $str;
}
Timings:
Dark: 0.12173390388489
Rich:0.15515804290771
@richthegeek It's always good to see someone who can really optimize their code effectively.
Thanks for the update as well, it's always appreciated.
I personally don't think that there is really that much in either of them, even before you optimized your code, if anything I would lean towards using your function over mine, even at the extra cost of 0.03* seconds. Solely because yours does a better job than mine does.
Good work!