10

uniqid() function returns a 13 digits long hexadecimal number. According to the spec in php.net site, the function uses microtime to generate the unique value.

But microtime returns numbers in string format as the following one:

"0.70352700 12689396875"

which are basically the microseconds and the seconds elapsed since 1970. This is a 9+11 digits decimal number.

Converting a 20 decimal number into hex would result in a 16 digits hexadecimal NOT a 13 digits one.

I also thought to take out the "0." part that seem to never change, and the last two digits of the microsec part that seem to remain always "00". Doing this the decimal number would be only 9+11-3 digits long, but still a decimal number of 17 digits when converted into hex would result in 14 digits hexadecimal number NOT 13.

I'M NOT INTERESTED IN GETTING A UNIQUE ID IN ANOTHER WAY OR A LONGER/SHORTER UNIQUE ID! I'M ONLY ASKING IF SOMEONE KNOWS WHY DOES uniqid RETURNS ONLY 13 DIGITS.

It seems nosense: if uniqid returns one digit less than microtime, it means that microtime gives out results that are more unique of the ones returned by uniqid.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
  • You should use the more_entropy option, it gives you a much more unique result. – St. John Johnson Mar 18 '10 at 19:52
  • 1
    Don't need more unique, I need to know why the result is only 13 chars long. Thanks anyway for the suggestion. – Marco Demaio Mar 18 '10 at 19:55
  • The most signifigant bits of microtime don't very often at all. So they're pretty useless, when you're trying to generate two unique strings within a few milliseconds of eachother. All timestamps for the next week will start with 126. And, should you manage to call uniqid() twice in the same microsecond (be it in two different threads or two different servers), you'll find its results won't be very unique at all. – Frank Farmer Mar 18 '10 at 20:08
  • 7
    If you REALLY want to know why it's 13 characters, **download and read the source code**. – Powerlord Mar 18 '10 at 20:10
  • @Powerlord: I had to write all uppercase bold because everyone was replying to my question explaining me other way to get unique id. I simply tried to make it more clear. – Marco Demaio Mar 22 '10 at 11:01

4 Answers4

20

Found this on http://www.php.net/manual/en/function.uniqid.php#95001

Makes sense to me. Comment if you need an explanation

For the record, the underlying function to uniqid() appears to be roughly as follows:

$m=microtime(true); sprintf("%8x%05x\n",floor($m),($m-floor($m))*1000000);

In other words, first 8 hex chars = Unixtime, last 5 hex chars = microseconds. This is why it has microsecond precision. Also, it provides a means by which to reverse-engineer the time when a uniqid was generated:

date("r",hexdec(substr(uniqid(),0,8)));

Increasingly as you go further down the string, the number becomes "more unique" over time, with the exception of digit 9, where numeral prevalence is 0..3>4>5..f, because of the difference between 10^6 and 16^5 (this is presumably true for the remaining digits as well but much less noticeable).

Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
KTastrophy
  • 1,739
  • 15
  • 23
8

I think the number generated by uniqid is based on the current time in microseconds -- but it is not that time : the calculation is probably a bit harder that you think.

Still, if you need more than 13 digits, you can pass true as a second parameter to uniqid, to have more entropy -- and it'll give you a string that's 23 characters longs.


For instance, with this portion of code :

var_dump(uniqid());
var_dump(uniqid('', true));

I just got :

string '4ba284384e4ca' (length=13)
string '4ba284384e4df9.73439132' (length=23)
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • 1
    This does not answer to my question, the point remains why the uniqid function returns a value that is only 13 chars long. Since is missing a digit, it can't' be as unique as microtime() function. Anyway thanks for the suggestion. – Marco Demaio Mar 18 '10 at 20:03
  • 2
    A Unix timestamp's seconds can 'fit' within 8 hexadecimal characters up to early Feb 2106 ((hex) `FFFFFFFF` is (dec) `4294967295`). A microsecond is one millionth of a second so the largest microsecond value is `999999` (any larger and it will be the next whole second) or `F423F` in hexadecimal. So: 13 hexadecimal characters to represent Unix time to the microsecond. – salathe Mar 18 '10 at 21:58
2

For a 32 character unique ID try this:

$unique = uniqid(rand(), true);

To shorten it just use substr():

$unique = substr(uniqid(rand(), true), 16, 16); // 16 characters long
John Conde
  • 217,595
  • 99
  • 455
  • 496
-3

Per the PHP manual the Default is 13 with the $more_entropy set to true it will be 23, but you will always end up with a Unix Timestamp.

I often use $uid = md5( uniqid() );

Update:
Now this will give you 32 characters with a minimal chance of collision is this lifetime.

md5(uniqid(mt_rand(), true)); 
Michael D. Irizarry
  • 6,186
  • 5
  • 30
  • 35