You can do that without unclean/costy stuff like loops, String concatenations or multiple calls to rand(), in a clean and easy to read way. Also, it is better to use mt_rand()
:
function createRandomString($length)
{
$random = mt_rand(0, (1 << ($length << 2)) - 1);
return dechex($random);
}
If you need the String to have the exact length in any case, just pad the hex number with zeros:
function createRandomString($length)
{
$random = mt_rand(0, (1 << ($length << 2)) - 1);
$number = dechex($random);
return str_pad($number, $length, '0', STR_PAD_LEFT);
}
The "theoretical backdraw" is, that you are limited to PHPs capabilities - but this is more a philosophical issue in that case ;) Let's go through it anyways:
- PHP is limited in what it can represent as a hex number doing it like this. This would be
$length <= 8
at least on a 32bit system, where PHPs limitation for this should be 4.294.967.295 .
- PHPs random number generator also has a maximum. For
mt_rand()
at least on a 32bit system, it should be 2.147.483.647
- So you are theoretically limited to 2.147.483.647 IDs.
Coming back to the topic - the intuitive do { (generate ID) } while { (id is not uniqe) } (insert id)
has one drawback and one possible flaw that might drive you straight to darkness...
Drawback: The validation is pessimistic. Doing it like this always requires a check at the database. Having enough keyspace (for example length of 5 for your 10k entries) will quite unlikely cause collisions as often, as it might be comparably less resource consuming to just try to store the data and retry only in case of a UNIQUE KEY error.
Flaw: User A retrieves an ID that gets verified as not taken yet. Then the code will try to insert the data. But in the meantime, User B entered the same loop and unfortunately retrieves the same random number, because User A is not stored yet and this ID was still free. Now the system stores either User B or User A, and when attempting to store the second User, there already is the other one in the meantime - having the same ID.
You would need to handle that exception in any case and need to re-try the insertion with a newly created ID. Adding this whilst keeping the pessimistic checking loop (that you would need to re-enter) will result in quite ugly and hard to follow code. Fortunately the solution to this is the same like the one to the drawback: Just go for it in the first place and try to store the data. In case of a UNIQUE KEY error just retry with a new ID.
Random::alphaLowercaseString(6)
, or a length of 8 or 10, as you wish. – Hyacinthe