Andy123 Posted February 1, 2013 Share Posted February 1, 2013 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. Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/ Share on other sites More sharing options...
PFMaBiSmAd Posted February 1, 2013 Share Posted February 1, 2013 It would be easy for a computer to cycle through all possible 7 digit numbers until it finds one that works. Why do you need an id that's so short and made up of a small set of characters? Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409522 Share on other sites More sharing options...
Andy123 Posted February 1, 2013 Author Share Posted February 1, 2013 (edited) 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 February 1, 2013 by Andy123 Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409525 Share on other sites More sharing options...
Jessica Posted February 1, 2013 Share Posted February 1, 2013 (edited) 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 February 1, 2013 by Jessica Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409527 Share on other sites More sharing options...
PFMaBiSmAd Posted February 1, 2013 Share Posted February 1, 2013 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. Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409528 Share on other sites More sharing options...
jay7981 Posted February 3, 2013 Share Posted February 3, 2013 or you could just use rand() with time() and generate a completely unique string $random = substr(number_format(time() * rand(),0,'',''),0,7); Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409812 Share on other sites More sharing options...
.josh Posted February 3, 2013 Share Posted February 3, 2013 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. Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409816 Share on other sites More sharing options...
.josh Posted February 3, 2013 Share Posted February 3, 2013 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... Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409817 Share on other sites More sharing options...
Andy123 Posted February 3, 2013 Author Share Posted February 3, 2013 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. Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409851 Share on other sites More sharing options...
kicken Posted February 3, 2013 Share Posted February 3, 2013 (edited) 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 February 3, 2013 by kicken Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409858 Share on other sites More sharing options...
Andy123 Posted February 3, 2013 Author Share Posted February 3, 2013 (edited) 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 February 3, 2013 by Andy123 Quote Link to comment https://forums.phpfreaks.com/topic/273915-generate-unique-user-id-integer/#findComment-1409887 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.