Use PHP functions in JavaScript

JavaScript uniqid

Generates a unique ID

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
function uniqid (prefix, more_entropy) {
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kankrelune (http://www.webfaktory.info/)
    // %        note 1: Uses an internal counter (in php_js global) to avoid collision
    // *     example 1: uniqid();    // *     returns 1: 'a30285b160c14'
    // *     example 2: uniqid('foo');
    // *     returns 2: 'fooa30285b1cd361'
    // *     example 3: uniqid('bar', true);
    // *     returns 3: 'bara20285b23dfd1.31879087'    if (typeof prefix == 'undefined') {
        prefix = "";
    }
 
    var retId;    var formatSeed = function (seed, reqWidth) {
        seed = parseInt(seed, 10).toString(16); // to hex str
        if (reqWidth < seed.length) { // so long we split
            return seed.slice(seed.length - reqWidth);
        }        if (reqWidth > seed.length) { // so short we pad
            return Array(1 + (reqWidth - seed.length)).join('0') + seed;
        }
        return seed;
    }; 
    // BEGIN REDUNDANT
    if (!this.php_js) {
        this.php_js = {};
    }    // END REDUNDANT
    if (!this.php_js.uniqidSeed) { // init seed with big random int
        this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
    }
    this.php_js.uniqidSeed++; 
    retId = prefix; // start with prefix, add current milliseconds hex string
    retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8);
    retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string
    if (more_entropy) {        // for more entropy we add a float lower to 10
        retId += (Math.random() * 10).toFixed(8).toString();
    }
 
    return retId;}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
uniqid();

Should return

1
'a30285b160c14'

» Example 2

Running

1
uniqid('foo');

Should return

1
'fooa30285b1cd361'

Dependencies

No dependencies, you can use this function standalone.

Open syntax issues

php.js uses JsLint to help us keep our code consistent and prevent some common bugs.

Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.


Authors

Thanks to the following developers, you get to have uniqid goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Mehmet Hazar Artuner
18 Dec '11 Permalink

q  thank you so much, you saved my life :D :D

Gravatar
Kevin van Zonneveld
10 Jun '09 Permalink

q  @ Kankrelune: Ok must be a caching issue then. I will try and see if I can reproduce it.

Gravatar
Kankrelune
2 Jun '09 Permalink

q  Yes me to... i don't see the difference today but the code is not the same than yesterday... a cache problem or i don't know... i was not drunked yet... lol... .. .

@ tchaOo°

Gravatar
Kevin van Zonneveld
2 Jun '09 Permalink

q  @ Kankrelune: Great job! Added!

(ps: I don't see a difference between the text file you uploaded and the source below, seems ok? am I not seeing it or was it different before?)

Gravatar
Kankrelune
1 Jun '09 Permalink

q  the code is not complete... it's a strange bug i have the same when i post version_compare()

http://www.webfaktory.info/uniqid.txt

@ tchaOo°

Gravatar
Kankrelune
1 Jun '09 Permalink

q  Final version without collisions...

function uniqid( prefix, more_entropy)
{
    // string uniqid( [ str prefix, [ bool more_entropy ]])
    // Generates a unique ID  
    // 
    // version: 
    // discuss at: http://phpjs.org/functions/uniqid
    // +   original by: Kankrelune (http://www.webfaktory.info/)
    // *     example 1: uniqid();
    // *     returns 1: 'a30285b160c14'
    // *     example 2: uniqid('foo');
    // *     returns 2: 'fooa30285b1cd361'
    // *     example 3: uniqid('bar', true);
    // *     returns 3: 'bara20285b23dfd1.31879087'
    if(typeof prefix == 'undefined')
        prefix = "";
    
    var retId;
    var formatSeed = function(seed, reqWidth) {
        seed = parseInt(seed,10).toString(16); // to hex str
        if (reqWidth < seed.length) { // so long we split
            return seed.slice(seed.length - reqWidth);
        }
        if (reqWidth > seed.length) { // so short we pad
            return Array(1 + (reqWidth - seed.length)).join('0')+seed;
        }
        return seed;
    };
    
    // BEGIN REDUNDANT
    if (!this.php_js) {
        this.php_js = {};
    }
    // END REDUNDANT
    if (!this.php_js.uniqidSeed) { // init seed with big random int
        this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
    }
    this.php_js.uniqidSeed++;
    
    retId = prefix; // start with prefix, add current milliseconds hex string 
    retId += formatSeed(parseInt(new Date().getTime()/1000,10),8);
    retId += formatSeed(this.php_js.uniqidSeed,5); // add seed hex string
    
    if(more_entropy) // for more entropy we add a float lower to 10
        retId += (Math.random()*10).toFixed(8).toString();
    
    return retId;
}



tested on 500.000 ids generated with the same prefix... .. . ;o)

@ tchaOo°

Gravatar
Kankrelune
1 Jun '09 Permalink

q  Hi... you're revisited version don't work...

on start replace

prefix +=  '';



by the original code...

if(typeof prefix == 'undefined')
    prefix = "";



i have made this for a simple cause... an undefined var is casted to a string she's transformed to a string with for contents "undefined" and after the ids is malformed...

undefinded4a2027b600c14

I think it's not a good idea to use an uniqid var on the uniqid function... it's a risk to dev confusion and namespace collision (? i speak english same as a spanish cow lol)

rename he to id or other is better... same for...

return this.uniqid(prefix, more_entropy, reduce_collision);



>>

return uniqid(prefix, more_entropy, reduce_collision);



Bye

Gravatar
Kevin van Zonneveld
31 May '09 Permalink

q  @ Kankrelune: Agreed but I believe the way it's set up now it will only generate a new number every second. If this function is used in a loop, you may get many iterations ( ids ) per second, and so there's nothing really unique about those.

If we fix the bug it will be much better, for now I have to leave the current implementation in tact though.

Gravatar
Kankrelune
31 May '09 Permalink

q  Hi... i have allredy think to store the ids and re generate if collision but i don't like this idea... and i don't like the 3rd parameter... .. . :o)

On the last test i have 20/35 collisions for 10.000 ids generate with the same prefix... for me 0.2% of collision it's more like PHP than a 3rd parameter... .. . ;o)

I know where is the problem... i work on when i have time... .. .
@ tchaOo°

ps: sorry for my english

Gravatar
Kevin van Zonneveld
31 May '09 Permalink

q  @ Kankrelune: Thanks a lot for investing your time! I would really like to have the implementation like PHP, but it still needs some work. Checkout comments here:

http://trac.plutonia.nl/projects/phpjs/browser/trunk/functions/misc/uniqid.js

Gravatar
Kankrelune
31 May '09 Permalink

q  Updated version without sprintf() dependencie and a lower collisions ratio (30/10.000)...

// uniqid( [ str prefix, [ bool more_entropy ]])
// Generate a unique ID 
// +     original by: Kankrelune (http://www.webfaktory.info/)
// *     example 1: uniqid();
// *     returns 1: 4a2027b600c14
// *     example 2: uniqid( time());
// *     returns 2: 12436214644a20285a07b3f
// *     example 3: uniqid( time(), true);
// *     returns 3: 12436214644a20285b1cd361.31879087

function uniqid( prefix, more_entropy)
{
    if(typeof prefix == 'undefined')
        prefix = "";
    
    var now, sec, usec;
    var formatBase = function(value, reqWidth) {
        value = (value >>> 0).toString(16);
        
        if (reqWidth > value.length)
            return Array(1 + (reqWidth - value.length) >>> 0).join('0') + value;
        if (reqWidth < value.length)
            return value.slice(0,reqWidth);
        
        return value;
    };
    var getRandSeed = function() {
        return [
                0xa524,0x11f9b,0x11c3a,0x7f5e,0xbe31,0x585a,0xc9c9,0xbee7,0x6a0f,0x8cb2,
                0x713e,0x11b99,0x4b7f,0x81f9,0x5e8d,0x15f34,0x57a9,0x10658,0x300d,0xa5da,
                0x13150,0xdf23,0x31b5,0x16fbc,0x17260,0xda84,0x15d13,0x17dc4,0x6263,0x11909,
                0x147ab,0x99b0,0xacf1,0x10da2,0xeb0f,0x9616,0x3e5b,0xd8dd,0x9331,0x13cb4,
                0x6701,0x148e3,0x139a4,0x4e74,0x6e6c,0x1230a,0x73e9,0x4b87,0x49c2,0x1357a,
                0x96cb,0x5010,0x9bc6,0x4588,0x9306,0x18107,0x1599f,0x7c97,0x16229,0x441c
            ][Math.floor( ( Math.random( ) * this.length ) )];
    };
    var makeSeed = function(seed) {
        return seed * ((((Math.random() * getRandSeed()) * (Math.random() * getRandSeed())) * getRandSeed()) * getRandSeed());
    };
    now = new Date().getTime()/1000;
    sec = parseInt(now,10);
    usec = Math.round((now-sec)*1000)/1000;
   
    if(more_entropy) // for more entropy we add a float lower to 10
        return prefix+formatBase(sec,8)+formatBase(makeSeed(usec),5)+(Math.random()*10).toFixed(8);
    
    return prefix+formatBase(sec,8)+formatBase(makeSeed(usec),5);
}



@ tchaOo°

Gravatar
Kankrelune
29 May '09 Permalink

q  I did the conversion. It works correctly, there are some collisions when more_entropy is false, but nothing really bad + / - 50 or 60 per 10,000 id created with the same prefix ...

-> http://img33.imageshack.us/img33/1899/testsa.png

// uniqid( [ str prefix, [ bool more_entropy ]])
// Generate a unique ID 
// +     original by: Kankrelune (http://www.webfaktory.info/)
// -     depends on: sprintf
// *     example 1: uniqid();
// *     returns 1: 4a2027b600c14
// *     example 2: uniqid( time());
// *     returns 2: 12436214644a20285a07b3f
// *     example 3: uniqid( time(), true);
// *     returns 3: 12436214644a20285b1cd361.31879087
function uniqid( prefix, more_entropy)
{
    if(typeof prefix == 'undefined')
        prefix = "";
        
    var now, sec, usec;
    now = new Date().getTime()/1000;
    sec = parseInt(now,10);
    usec = Math.round((now-sec)*1000)/1000;
    
    if(more_entropy) // for more entropy we add a float lower to 10
        return sprintf("%s%08x%05x%s",prefix,sec,(usec*(Math.random()*999999)),(Math.random()*10).toFixed(8));
    
    return sprintf("%s%08x%05x",prefix,sec,(usec*(Math.random()*999999)));
}



@ tchaOo°

Gravatar
Kevin van Zonneveld
19 Apr '09 Permalink

q  @ Michael Grier: That was exactly what I needed :D great. I will process the C code when I find the time. Thanks a lot, I'll make sure to mention your name in the final version.

Gravatar
Brett Zamir
16 Apr '09 Permalink

q  Aha...Gotcha...Thanks

Gravatar
Michael Grier
15 Apr '09 Permalink

q  That wasn't my point. Kevin just mentioned in the comments of the function that "we need to checkout the PHP source to find out how they generate this exactly," so since nobody else "seemed" to have done this (there are no other comments here about it), I looked for and posted the source.

Gravatar
Brett Zamir
15 Apr '09 Permalink

q  Hi Michael,

While it's great to use heavier algorithms, such as in the PHP source, I think our initial focus is on replicating the PHP API regardless of implementation--if you can make any implementations more robust (and/or speed them up), go for it! :)

Gravatar
Michael Grier
14 Apr '09 Permalink

q  Here's the 5.2.9 source for uniqid.c and lcg.c

http://mgrier.com/te5t/uniqid-source.txt
(you can click my name for same page)

Here's the short version of "more_entropy"

/*
 * combinedLCG() returns a pseudo random number in the range of (0, 1).
 * The function combines two CGs with periods of 
 * 2^31 - 85 and 2^31 - 249. The period of this function
 * is equal to the product of both primes.
 */


Contribute a New function

More functions

In this category

constant
define
defined
pack
php_strip_whitespace
time_sleep_until
» uniqid

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: AYHAN BARI*, Nikita Ekshiyan, Nikita Ekshiyan, Petr Pavel, @HalfWinter, Paulo Freitas, Andros Peña Romo, @andorosu, Raimund Szabo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !