Jump to content

Recommended Posts

I would like to generate a unique user ID per user which should be an integer and with a length of 7. I do not want to use a hashing algorithm since collisions are possible. Since I will be putting these IDs in my URLs, it would be great if they could be pretty integers. They will be stored in a column with a unique index, so they must be unique. I do not want the IDs to be predictable or sequential.

 

I looked into uniqid(), which looked pretty useful except that it does not return an integer. Simply using time() seems pretty safe too, but it is too long. Each user will obviously have a unique username, so perhaps that could be used in generating the ID - perhaps along with the microtime? It would be simple to use uniqid() with the username as a prefix, but that will not give me an integer.

 

Any ideas on how I can do this? Is it even possible, or do I need to use sequential numbers?

 

Thanks.

Link to comment
https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/
Share on other sites

It is true that I could create a loop, but I need to generate this identifier during user registration. This means that I would have to probe the database to see if each generated identifier is available. Sure I could do this from within a stored procedure to save some time, but I would still have to execute a query. But I guess as long as I do not check the generated codes sequentially, it would be a decent solution. If I were to check it sequentially, the day when the first N combinations are taken, then I'd be looping and probing N times pointlessly. Do you mean something like this?

 


$identifier = '';
$i = 0;

while ($i < 7) {
$identifier .= rand(0, 9);

$i++;
}

$identifier = (int) $identifier;

// Check identifier availability and do the above again if it is not available

 

Surely it is unlikely that this would result in collisions for quite a long time, given that there are 10^7 possible combinations (correct?).

 

The reason why I want a short identifier is mostly cosmetic; 5972857 looks better in an URL than dsah3y39gyags2dsaf2. Also, 7 characters gives me plenty of possible combinations if I am not mistaken, provided that there is a way that I can make use of them without too much trouble (i.e. handling collissions). I could go with my approach, but I just wanted to know if there was a better way so I did not have to handle collisions myself.

Edited by Andy123

And why can't you use sequential numbers?

 

You know what looks even better in a URL? a name. People can't remember a 7 digit number. (Edit: that has no significance to them. And even if it does they usually can't. Ask any husband.)

Edited by Jessica

Because computers are not good at generating truly random numbers, the random number/loop method will have a problem when you have used a majority of the available numbers as it will take more and more passes through the loop (and database queries) before you find an unused number and you may reach a point where that method cannot find an unused number.

 

To do what you are asking, you should generate all the possible numbers, in sequence, in an array, randomize them, then store them in a database table. Then you just get the first unused number and either mark it as being used or delete it.

If it must be an integer, then I would go with Jesirose's suggestion to just make it sequential. If you can let it be alphanumeric, an easy way would be to

 

dechex(time())

 

If this still doesn't work for you, the next reliable method would be to just generate a random integer and look up in your db if it already exists. Wrap it in a while loop until one is generated that doesn't exist. This could conceivably become an issue when you start to have lots of numbers to lookup against, but that's something you're gonna have to live with, given your current restrictions.

or you could just use rand() with time() and generate a completely unique string :)

 

$random = substr(number_format(time() * rand(),0,'',''),0,7);

 

this won't really work, there's potential for collision. Since you are multiplying by random and then substringing...throwing time() into the mix is pretty useless...

Thanks for the ideas, guys. I ended up with a quite alternative approach where I use my primary key (which is obviously unique) to generate my user code. I manipulate it a bit to obscure the pattern, such that my user codes are both unique, but also less predictable. I think what I did was this (done in a stored procedure):

 

$user_code = (rand(1,9) + ($primary_key + 164) + rand(0,9));

 

It may seem silly, but it makes it hard to figure out a pattern if you are not aware of the implementation. Surely this is not random, but I guess that's okay after all. Since the primary key is sequential, the middle part of the addition will always be a unique number and thus, I will not have collisions. At least that's what I think; if someone disagrees, please let me know. :)

Since the primary key is sequential, the middle part of the addition will always be a unique number and thus, I will not have collisions. 

 

There is still a potential for collision, albeit small.  For example:

rand(1,9) = 5
$primary_key = 17865
rand(0,9) = 6
= 17876

rand(1,9) = 5
$primary_key = 17867
rand(0,9) = 4
= 17876

Edited by kicken

There is still a potential for collision, albeit small. For example:

rand(1,9) = 5
$primary_key = 17865
rand(0,9) = 6
= 17876

rand(1,9) = 5
$primary_key = 17867
rand(0,9) = 4
= 17876

 

Thank you for the heads up. Actually, I made a silly mistake in my previous post. What I really did was to concatenate instead of add. So the line in my previous post should have been something like this instead:

 

$user_code = (int) (rand(1,9) . ($primary_key + 164) . rand(0,9));

 

Sorry for the confusion.

Edited by Andy123
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.