2010-03-18 10 views
9

uniqid() restituisce un numero esadecimale lungo 13 cifre. Secondo lo spec in php.net site, la funzione utilizza microtime per generare il valore univoco.Perché la funzione uniqid di PHP restituisce solo 13 cifre e non 14?

Ma microtime restituisce i numeri in formato stringa come il seguente:

"0.70352700 12689396875" 

che sono fondamentalmente i microsecondi ed i secondi trascorsi dal 1970. Questo è un numero decimale 9 + 11 cifre.

La conversione di un numero decimale da 20 in esadecimale risulterebbe in un numero esadecimale di 16 cifre esadecimali non a 13 cifre .

Ho anche pensato di estrarre lo "0". parte che sembra non cambiare mai, e le ultime due cifre della parte microsec che sembrano rimanere sempre "00". In questo modo il numero decimale sarebbe lungo solo 9 + 11-3 cifre, ma ancora un numero decimale di 17 cifre quando convertito in esadecimale si tradurrebbe in 14 cifre numero esadecimale NON 13.

io non sono interessato a COME OTTENERE UN ID UNICO IN UN ALTRO MODO O UN ID PIÙ UNICO PIÙ LUNGO/CORRETTO! STO FACENDO SOLTANTO SE QUALCUNO CONOSCE PERCHÉ uniqid RESTA SOLO 13 CIFRE.

Sembra nosense: se uniqid restituisce una cifra inferiore a microtime, significa che microtime dà fuori i risultati che sono più unici di quelli restituiti da uniqid.

+0

Dovresti usare l'opzione more_entropy, ti dà un risultato molto più unico. –

+1

Non ho bisogno di altro, ho bisogno di sapere perché il risultato è lungo solo 13 caratteri. Grazie comunque per il suggerimento. –

+0

I bit più significativi di microtime non lo fanno molto spesso. Quindi sono piuttosto inutili, quando stai cercando di generare due stringhe uniche in pochi millisecondi l'una dall'altra. Tutti i timestamp per la prossima settimana inizieranno con 126. E, se dovessi chiamare uniqid() due volte nello stesso microsecondo (sia in due thread differenti o in due server diversi), scoprirai che i suoi risultati non saranno molto assolutamente unico. –

risposta

19

Trovato questo su http://www.php.net/manual/en/function.uniqid.php#95001

ha senso per me. Commento se avete bisogno di una spiegazione

Per la cronaca, la funzione di sottostante a uniqid() sembra essere o meno come segue:

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

In altre parole, primi 8 caratteri esadecimali = Unixtime, ultimi 5 caratteri esadecimali = microsecondi. Questo è il motivo per cui ha una precisione di microsecondi pari a . Inoltre, fornisce un mezzo per decodificare il momento in cui un'uniqid stata generata:

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

Sempre più spesso, come si va più in basso la stringa, il numero diventa "più unico" nel corso del tempo, con l'eccezione di cifra 9, dove la prevalenza numerica è 0..3> 4> 5..f, a causa della differenza tra 10^6 e 16^5 (questo è presumibilmente vero per le restanti cifre ma molto meno notevole).

7

penso che il numero generato dal uniqid è base l'ora corrente in microsecondi - ma non è che il tempo: il calcolo è probabilmente un po 'più difficile che si pensi.

Ancora, se hai bisogno di più di 13 cifre, puoi passare true come secondo parametro a uniqid, per avere più entropia - e ti darà una stringa di 23 caratteri.


Ad esempio, con questa porzione di codice:

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

Ho appena ricevuto:

string '4ba284384e4ca' (length=13) 
string '4ba284384e4df9.73439132' (length=23) 
+0

Questo non risponde alla mia domanda, resta il motivo per cui la funzione uniqid restituisce un valore lungo solo 13 caratteri. Poiché manca una cifra, non può essere unica come la funzione microtime(). Comunque grazie per il suggerimento. –

+2

I secondi di un timestamp Unix possono "adattarsi" a 8 caratteri esadecimali fino all'inizio di febbraio 2106 ((esadecimale) 'FFFFFFFF' è (decimale)' 4294967295'). Un microsecondo è un milionesimo di secondo, quindi il valore microsecond più grande è "999999" (qualsiasi più grande e sarà il secondo intero successivo) o "F423F" in esadecimale. Quindi: 13 caratteri esadecimali per rappresentare il tempo Unix al microsecondo. – salathe

0

Per un 32 carattere unico ID provare questo:

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

Per accorciare basta usare substr():

$unique = substr(uniqid(rand(), true), 16, 16); // 16 characters long 
+4

Non inciderebbe gravemente sulle possibilità di duplicati? – Tom

+0

Le possibilità sarebbero comunque estremamente ridotte e praticamente improbabili. Tuttavia, se l'obiettivo era quello di garantire la massima unicità, è necessario utilizzare l'intero MD5. –

+2

Stai aggiungendo caratteri, ma riducendo entropia e unicità. –

-3

Per il manuale PHP il valore predefinito è 13 con $ more_entropy impostato su true sarà 23, ma si finirà sempre con un timestamp Unix.

Io uso spesso $uid = md5(uniqid());

Aggiornamento:
Ora questo vi darà 32 caratteri con una minima probabilità di collisione è questa vita.

md5(uniqid(mt_rand(), true)); 
+4

' md5() 'non introduce più alcuna entropia. Se mai, rimuove un po ', poiché c'è una piccola possibilità di collisione di hash. –

+1

'md5' non è resistente alle collisioni e non dovrebbe essere usato come per questo – Petah

+0

Scusate il mio male, ho completamente dimenticato di aggiungere l'esempio completo md5 (uniqid (mt_rand(), true)); uniqid è quello che ha più entropia. –

Problemi correlati