I am trying to come up with a solution to generate a Unique Id preferably on the Fly. Usage scope could be Order, Product or Plan Id, where there is no security involved.
I don't like idea of generating a random number and then querying the db to check its uniqueness and repeating the process if it is not in this case where security isn't an issue.
Also I don't prefer using Auto Increment id since it looks so simple.
My initial thought is to use a combination of Auto Increment id + timestamp converting the decimal value to hex so it looks like a random string. And then finally prefixing and suffixing it with 2 digit random string.
function generateUID($num){
$str = dechex(time()+ intval($num));
$prefix = dechex(rand(1,15));
$suffix = dechex(rand(1,15));
return strtoupper($suffix.$str.$prefix);
}
Where $num is the auto_increment id
Returns something like E53D42A046
Is this the right way to go about doing this, are there collision issues ?
I thank all responses..!
I acknowledge the usefulness of uniqid() but in this context to be genuinely unique Auto_Increment need to play a significant part so how will it do so in uniqid. Passing it as a prefix would result in a Product id which vary greatly in size. (153d432da861fe, 999999953d432f439bc0).
To expand the scope further, Ideally we want a unique code which looks random with fairly consistent length and could be reversed to the auto_increment id from which it was created.
Such a function already exists - uniqid()
http://php.net/manual/en/function.uniqid.php
It works based on the timestamp down to the microsecond - you can add a prefix based on the process ID to further refine it. There are a couple more robust versions out there as well - see PHP function to generate v4 UUID
Related
I'm making a data base and I would like to get two unique ids from each player like clash royale game .
1.id unique only number (It knows only the user)
2.id unique number and letters (all the players can see it).
I was thinking of using the time to get the first unique id, and then add a random number, but I think this would create a string that is too long.
Moreover it does not guarantee 100% yet to obtain a unique id.
I'm working with PHP and MySQL
https://secure.php.net/manual/en/function.uniqid.php
It won't return a numeric string, for that I guess you could use microtime plus a sufficiently long random number to limit the chances of collision to virtually nil. But why not use uniqid for both?
I'm using mysql database auto-increment as an order ID. When I display the order ID to the user, I want to somehow mask/obfuscate it.
Why?
So at first glance, it is obvious to admin users what the number
refers to (orders start with 10, customers start with 20 etc)
To hide, at first glance, that this is only my 4th order.
Based on this this answer, I want the masked/obfuscated order id to:
Be only numbers
Consistent length (if possible)
Not cause collisions
Be reversible so I can decode it and get the original ID
How would I acheive this in PHP? It doesn't have to be very complex, just so at first glance it's not obvious.
I think you can use XOR operator to hide "at first glance" for example (MySQL example):
(id*121) ^ 2342323
Where 2342323 and 121 are "magic" numbers - templates for the order number.
To reverse:
(OrderNum ^ 2342323)/121
Additional advantage in this case - you can validate OrderNumber (to avoid spam or something like this in online form) if (OrderNum ^ 2342323) is divided by 121 with no remainder.
SQLFiddle demo
A little bit late, but Optimus (https://github.com/jenssegers/optimus) does exactly what is here asked for.
$encoded = $optimus->encode(20); // 1535832388
$original = $optimus->decode(1535832388); // 20
Only the initial setup is a bit weird (generate primenumbers)
Probably the simplest way is to just generate a long random string and use it instead of the auto-increment ID. Or maybe use it alongside the auto-increment ID. If the string is long enough and random enough, it will be unique for every record (think of GUIDs). Then you can display these to the user and not worry about anything.
Can it help?
echo hexdec(uniqid());
Off course you should store this value at db, at the same row with order id.
Just converting a ID into something like HEX might not give you the result what you like. Moreover its still easy 'guessable'
I would a a extra ID column (i.e. order_id). Set a unqi. index. Then on_creation use one of the following mysql functions:
SHA1(contcat('ORDER', id))
MD5(contcat('ORDER', id))
SHA1(contcat('ORDER', id, customer_id))
MD5(contcat('ORDER', id, customer_id))
UUID()
// try this in your mysql console
SELECT UUID(), SHA(CONCAT('ORDER',10)), SHA1(1);
You could (as in the example), add a simple text prefix like 'order'. Or even combine them. However i think UUID() would be easiest.
Implementation depends a bit on what you prefer you could use a stored procedure) or incorporate it in your model.
Is there any way I could make my model ID (primary key) generated into random unique 8 digits containing only numbers instead of the default auto increment?
A client requested this specific 8-digits-number-only feature, so I can't argue much about the reasons.
I want to use the PHP uniqid but it's 13 digits and contains alphabets as well.
Any idea?
Thanks.
Update
I forgot to tell that I need the ID randomly generated each new record being saved.
Just want to ask the mechanism on generating the ID and then saving the ID (also the attributes). Do I have to check the database first for the randomly generated ID whether another same key already exists and then save the attributes or what?
Why dont you keep the auto increment but set it to start from 10000000 on your primary key instead of 1?
ALTER TABLE some_table AUTO_INCREMENT=10000000
Yes you can. I assume you are on MySQL, when talking about AI. Just do not set it as auto increment and insert the value as for the other columns. You can create a function or method, which will take up to 8 numbers randomly or in specific order (algorithm).
INSERT INTO model (id, name, value, etc) VALUES (87654321, 'My selected name', 'some price or text', 'etc').
Consider that INT(11) value may accept from -2147483648 to 2147483647. Which will fit you for numbers with 8 digits. If at later time the client request bigger numbers you may need to switch to BIGINT.
I use to set the Primary Keys as unsigned, which allows you to fit numbers between 0 and 4294967295.
For php function - generator of 8 digits:
<?php
mt_srand();
$id = mt_rand(10000000, 99999999);
?>
You can read more about mt_srand() and mt_rand() on php documentation. It is said that they are better than the srand() and rand().
Keep the ID, but pad it.
$id = 6;
$padded_id = sprintf("%013d", $id);
// This will print 0000000000006
That'll pad the $id so that it's 13 digits long.
Every time you need to display the ID use a function to convert it, like this.
function padId($id){
return sprintf("%013d", $id);
}
Or you could make a row in your table called pad-id, then run this function when you create a record (along with mysql_insert_id (to get the ID just inserted)).
The best approach depends on a subtle aspect of your client's randomness requirement --
When they say random do they mean completely unpredictable or just hard to predict? I don't mean to sound like Clinton at the Lewinski trial, but what your client intends when they say random affects whether it will even be possible for you to meet the requirement.
If the client wants to hide user IDs (for some perceived security benefit) and make them virtually impossible to predict or reverse-engineer, then that is very difficult. If the client would be satisfied with just "hard" to predict (which I suspect), then you can do something simple, similar to the md5 approach (#Dotty). But md5 is not collision resistant. And even with the best, provably unique hash algorithms (which md5 is not), you'll have a collision problem if the number of users is large compared to the number of digits you are allowed for user ID's (8). You have about 27 bits to work with in the 8 decimal digits allowed. Which means you're likely to get a collision after 2^N/2 = 2^(27/2) which is about 10K users. So if your client's user list approaches 10K users, then even the best hash algorithm will spend a lot of time filtering out all the collisions.
To solve this without filters and nondeterministic algorithms, just use a simple "Full Cycle" algorithm. Some will produce pseudo-random numbers (PRNs) that are guaranteed to be unique and guaranteed to fully span whatever range you're trying to cover (e.g., the set of all 8-digit positive integers). And if you ever need to reverse engineer the user registration sequence just rerun the full cycle PRN generator again with whatever initial value you used. And you can keep this initial value a secret, like a private key, if your client wants to make it slightly more difficult than easy for a hacker to reverse-engineer your user ID sequence.
Another question for your client is whether leading zeros are allowed in the user id. If so, (and the client's randomness requirements are liberal) then the simple Full Cycle algorithm on Wikipedia will work nicely for you. It could be distilled to 2 lines of PHP.
Whatever algorithm you use, it might be good to actually generate the list of official 8-digit semi-random user IDs in a separate table, and then just "pop" the value from the top of the table (deleting that row) whenever you add a new user. The database memory requirements shouldn't be prohibitive and it will streamline the user experience, eliminating any delays and memory gobbling caused by sophisticated, nondeterministic, random number generators and uniqueness filters. Trying to create the user ID online, live, it's conceivable you could get into a perpetual loop with some hash algorithms stalling your user registration indefinitely. And this stall (due to perpetual collision) might not occur until user 1000 or 10000. In contrast, with the offline lookup table approach, you can easily add additional client-prescribed filters like eliminating IDs with leading zeros; in case the client never wants to see a user with the ID 1 (00000001). And you'd know in advance whether everything is going to always work, without any hangs.
I have seen a few post on this, but nothing that would work entirely for what I'm trying to do. Pretty much I want to generate a new id for clients in this script. What I want to do is add a new entry to my database, get the id, and then multiply by say A1A1, or something like that. So it would be like
A1A1 - 1st id
A1A2 - 2nd id
A1A3 - 3rd id
(so on and so fort).
Anyone got any ideas where I should start with that?
Just increment your string:
$id = 'A1A1';
$new_id = ++ $id; // $new_id is now A1A2
See it on Ideone
Not sure if this would work, but typically generates somewhat sequential hexdecimal numbers based on the current microsecond.
uniqid();
http://www.php.net/manual/en/function.uniqid.php
If you are using a SQL database, I would highly suggest checking out auto increment. For example, here is auto-increment for mysql.
You may split the whole id into alphabets and numerals. Then increment the corresponding numeral and concatenate back. If you have to make record deletion, take care of the re-arranging the sequence.
I'm trying to create a unique id that's random. This solution was suggested, but I'm not if it's guaranteed that they'll be unique.
function uid($n) {
$id_part = base_convert($n, 10, 36);
$rand_part = str_shuffle('abcdefghijklmnopqrstuvwxyz0123456789');
return sprintf("%05s%.15s", $id_part, $rand_part);
}
The code uses the unique id from the database auto-incremented id (that's the $n input I'm guessing), then some fill characters are added. It gives supposedly a "unique" 5 chars base-36 primary id + 15 rubbish chars. Can someone confirm if the result will indeed be unique ids or not.
To answer the question, what am I
doing this for exactly. I need to give
users a unique id, that doesn't
directly equal their user id in the
database. This way user 1 does not
know that he registered before user 2,
but each user still has to have a
unique "front id".
It will be unique within the table that $n comes from, as would $n alone without any extra random characters. It will not be globally unique across all applications ever, nor would any fixed length string. All you can guarantee is the probability of generating the same string twice.
You can try inbuilt functionalities like :
http://php.net/manual/en/function.uniqid.php
http://php.net/manual/en/function.com-create-guid.php
Depends how much uniqueness you want to have. If it is only for your application, or globally.
Globally Guid will be a better option.
$token = hash('sha256', rand() . microtime() . $_SERVER['REMOTE_ADDR']) // rand as possible