w3schools uniqid str_random ramsey number generate generar crear php uniqueidentifier unique-index

uniqid - str_random php



Identificación única corta en php (15)

function rand_str($len = 12, $type = ''111'', $add = null) { $rand = ($type[0] == ''1'' ? ''abcdefghijklmnpqrstuvwxyz'' : '''') . ($type[1] == ''1'' ? ''ABCDEFGHIJKLMNPQRSTUVWXYZ'' : '''') . ($type[2] == ''1'' ? ''123456789'' : '''') . (strlen($add) > 0 ? $add : ''''); if(empty($rand)) $rand = sha1( uniqid(mt_rand(), true) . uniqid( uniqid(mt_rand(), true), true) ); return substr(str_shuffle( str_repeat($rand, 2) ), 0, $len); }

Quiero crear una identificación única pero uniqid() da algo como ''492607b0ee414'' . Lo que me gustaría es algo similar a lo que da tinyurl: ''64k8ra'' . Cuanto más corto, mejor. Los únicos requisitos son que no debería tener un orden obvio y que debería verse más bonito que una secuencia de números aparentemente aleatoria. Las letras son preferibles a los números e idealmente no sería un caso mixto. Como el número de entradas no será tan alto (hasta 10000 o menos), el riesgo de colisión no es un factor enorme.

Cualquier sugerencia apreciada.


Hay dos maneras de obtener una identificación única fiable: hacerla tan larga y variable que las posibilidades de una colisión sean espectacularmente pequeñas (como con un GUID) o almacenar todas las ID generadas en una tabla para búsqueda (ya sea en la memoria o en una BD) o un archivo) para verificar la singularidad en la generación.

Si realmente está preguntando cómo puede generar una clave tan corta y garantizar su singularidad sin algún tipo de verificación duplicada, la respuesta es que no puede.


Podrías usar el Id y simplemente convertirlo a un número de base 36 si quieres convertirlo de ida y vuelta. Se puede usar para cualquier tabla con un ID entero.

function toUId($baseId, $multiplier = 1) { return base_convert($baseId * $multiplier, 10, 36); } function fromUId($uid, $multiplier = 1) { return (int) base_convert($uid, 36, 10) / $multiplier; } echo toUId(10000, 11111); 1u5h0w echo fromUId(''1u5h0w'', 11111); 10000

Las personas inteligentes probablemente puedan resolverlo con suficientes ejemplos de identificación. No dejes que esta oscuridad reemplace a la seguridad.


Esta es la rutina que uso para base62s aleatorias de cualquier longitud ...

Llamar a gen_uuid() devuelve cadenas como WJX0u0jV, E9EMaZ3P etc.

Por defecto, esto devuelve 8 dígitos, por lo tanto, un espacio de 64 ^ 8 o aproximadamente 10 ^ 14, esto es a menudo suficiente para hacer colisiones bastante raras.

Para una cadena más grande o más pequeña, pase $ len como desee. Sin límite de longitud, ya que añado hasta que esté satisfecho [hasta el límite de seguridad de 128 caracteres, que se puede quitar].

Tenga en cuenta que utilice una sal aleatoria dentro de md5 [o sha1 si lo prefiere], por lo que no se puede modificar de forma inversa.

No encontré ninguna conversión de base62 confiable en la web, de ahí este enfoque de eliminar caracteres del resultado base64.

Utilice libremente bajo la licencia de BSD, disfrute,

gord

function gen_uuid($len=8) { $hex = md5("your_random_salt_here_31415" . uniqid("", true)); $pack = pack(''H*'', $hex); $uid = base64_encode($pack); // max 22 chars $uid = ereg_replace("[^A-Za-z0-9]", "", $uid); // mixed case //$uid = ereg_replace("[^A-Z0-9]", "", strtoupper($uid)); // uppercase only if ($len<4) $len=4; if ($len>128) $len=128; // prevent silliness, can remove while (strlen($uid)<$len) $uid = $uid . gen_uuid(22); // append until length achieved return substr($uid, 0, $len); }


Solución realmente simple:

Haga la identificación única con:

$id = 100; base_convert($id, 10, 36);

Obtenga el valor original nuevamente:

intval($str,36);

No puedo atribuirme el mérito porque es de otra página de desbordamiento de pila, pero pensé que la solución era tan elegante e impresionante que valía la pena copiarla a este hilo para las personas que hacen referencia a esto.


@gen_uuid () por gord.

preg_replace tiene algunos problemas desagradables de utf-8, lo que hace que el uid algunas veces contenga "+" o "/". Para evitar esto, debes hacer explícitamente el patrón utf-8

function gen_uuid($len=8) { $hex = md5("yourSaltHere" . uniqid("", true)); $pack = pack(''H*'', $hex); $tmp = base64_encode($pack); $uid = preg_replace("#(*UTF8)[^A-Za-z0-9]#", "", $tmp); $len = max(4, min(128, $len)); while (strlen($uid) < $len) $uid .= gen_uuid(22); return substr($uid, 0, $len); }

Me tomó bastante tiempo encontrar eso, tal vez le ahorre a alguien más un dolor de cabeza


Se me ocurrió lo que creo que es una solución muy buena para hacer esto sin una verificación de exclusividad. Pensé que compartiría para cualquier visitante futuro.

Un contador es una forma realmente fácil de garantizar la exclusividad o, si está utilizando una base de datos, una clave principal también garantiza la exclusividad. El problema es que se ve mal y podría ser vulnerable. Así que tomé la secuencia y la mezclé con un cifrado. Como el cifrado se puede revertir, sé que cada identificación es única y sigue apareciendo aleatoriamente.

Es python no php, pero he cargado el código aquí: https://github.com/adecker89/Tiny-Unique-Identifiers


Si le gusta una versión más larga de identificación única, use esto:
$ uniqueid = sha1 (md5 (tiempo ()));


También puedes hacerlo como tihs:

public static function generateCode($length = 6) { $az = ''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ''; $azr = rand(0, 51); $azs = substr($az, $azr, 10); $stamp = hash(''sha256'', time()); $mt = hash(''sha256'', mt_rand(5, 20)); $alpha = hash(''sha256'', $azs); $hash = str_shuffle($stamp . $mt . $alpha); $code = ucfirst(substr($hash, $azr, $length)); return $code; }


Puede hacer eso sin cosas sucias / costosas como bucles, concatenaciones de cadenas o llamadas múltiples a rand (), de una manera limpia y fácil de leer. Además, es mejor usar mt_rand() :

function createRandomString($length) { $random = mt_rand(0, (1 << ($length << 2)) - 1); return dechex($random); }

Si necesita que String tenga la longitud exacta en cualquier caso, simplemente rellene el número hexadecimal con ceros:

function createRandomString($length) { $random = mt_rand(0, (1 << ($length << 2)) - 1); $number = dechex($random); return str_pad($number, $length, ''0'', STR_PAD_LEFT); }

El "backdraw teórico" es que estás limitado a las capacidades de PHP, pero esto es más un problema filosófico en ese caso;) Veámoslo de todos modos:

  • PHP está limitado en lo que puede representar como un número hexadecimal haciéndolo así. Esto sería $length <= 8 al menos en un sistema de 32 bits, donde la limitación de PHP para esto debería ser 4.294.967.295.
  • El generador de números aleatorios de PHP también tiene un máximo. Para mt_rand() al menos en un sistema de 32 bits, debería ser 2.147.483.647
  • Entonces, teóricamente estás limitado a 2.147.483.647 ID.

Volviendo al tema: el intuitivo do { (generate ID) } while { (id is not uniqe) } (insert id) tiene un inconveniente y un posible defecto que puede llevarte directamente a la oscuridad ...

Drawback: la validación es pesimista. Hacerlo así siempre requiere un control en la base de datos. Tener suficiente espacio de teclado (por ejemplo, 5 de longitud para sus entradas de 10k) es bastante improbable que provoque colisiones con tanta frecuencia, ya que podría ser menos consumo de recursos tratar de almacenar los datos y volver a intentarlos solo en caso de un error UNIQUE KEY.

Defecto: el usuario A recupera una identificación que se verifica como no tomada todavía. Entonces el código intentará insertar los datos. Pero, mientras tanto, el usuario B ingresó al mismo bucle y desafortunadamente recupera el mismo número aleatorio, porque el usuario A aún no se ha almacenado y esta ID todavía era gratuita. Ahora el sistema almacena el Usuario B o el Usuario A , y cuando intenta almacenar el segundo Usuario, ya existe el otro mientras tanto, con la misma ID.

Debería manejar esa excepción en cualquier caso y necesitar volver a intentar la inserción con una ID recién creada. Agregar esto mientras se mantiene el ciclo de control pesimista (que necesitaría volver a ingresar) dará como resultado un código bastante feo y difícil de seguir. Afortunadamente, la solución a esto es la misma que la de la desventaja: simplemente hazlo en primer lugar e intenta almacenar los datos. En caso de un error UNIQUE KEY, simplemente vuelva a intentar con una nueva ID.



Puedes lograr eso con menos código:

function gen_uid($l=10){ return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyz"), 0, $l); }

Resultado (ejemplos):

  • cjnp56brdy
  • 9d5uv84zfa
  • ih162lryez
  • ri4ocf6tkj
  • xj04s83egi

La mejor respuesta hasta el momento: la cadena "Hash Like" más pequeña con ID de base de datos única: solución PHP, no se requieren bibliotecas de terceros.

Aquí está el código:

<?php /* THE FOLLOWING CODE WILL PRINT: A database_id value of 200 maps to 5K A database_id value of 1 maps to 1 A database_id value of 1987645 maps to 16LOD */ $database_id = 200; $base36value = dec2string($database_id, 36); echo "A database_id value of 200 maps to $base36value/n"; $database_id = 1; $base36value = dec2string($database_id, 36); echo "A database_id value of 1 maps to $base36value/n"; $database_id = 1987645; $base36value = dec2string($database_id, 36); echo "A database_id value of 1987645 maps to $base36value/n"; // HERE''S THE FUNCTION THAT DOES THE HEAVY LIFTING... function dec2string ($decimal, $base) // convert a decimal number into a string using $base { //DebugBreak(); global $error; $string = null; $base = (int)$base; if ($base < 2 | $base > 36 | $base == 10) { echo ''BASE must be in the range 2-9 or 11-36''; exit; } // if // maximum character string is 36 characters $charset = ''0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ''; // strip off excess characters (anything beyond $base) $charset = substr($charset, 0, $base); if (!ereg(''(^[0-9]{1,50}$)'', trim($decimal))) { $error[''dec_input''] = ''Value must be a positive integer with < 50 digits''; return false; } // if do { // get remainder after dividing by BASE $remainder = bcmod($decimal, $base); $char = substr($charset, $remainder, 1); // get CHAR from array $string = "$char$string"; // prepend to output //$decimal = ($decimal - $remainder) / $base; $decimal = bcdiv(bcsub($decimal, $remainder), $base); } while ($decimal > 0); return $string; } ?>


Haga una pequeña función que devuelva letras aleatorias para una longitud determinada:

<?php function generate_random_letters($length) { $random = ''''; for ($i = 0; $i < $length; $i++) { $random .= chr(rand(ord(''a''), ord(''z''))); } return $random; }

Entonces querrás llamarlo hasta que sea único, en pseudocódigo dependiendo de dónde almacenarías esa información:

do { $unique = generate_random_letters(6); } while (is_in_table($unique)); add_to_table($unique);

También es posible que desee asegurarse de que las letras no formen una palabra en un dictionario. Puede ser todo el dictionario en inglés o simplemente un dictionario de mala palabra para evitar cosas que un cliente encontraría de mal gusto.

EDITAR: También añadiría que esto solo tiene sentido si, como pretende usarlo, no es para una gran cantidad de elementos, porque esto podría volverse bastante lento a medida que ocurran más colisiones (obtener una ID ya en la tabla). Por supuesto, querrá una tabla indexada y querrá ajustar el número de letras en la ID para evitar colisiones. En este caso, con 6 letras, tendría 26 ^ 6 = 308915776 posibles identificaciones únicas (menos malas palabras) que deberían ser suficientes para su necesidad de 10000.

EDITAR: Si quieres una combinación de letras y números, puedes usar el siguiente código:

$random .= rand(0, 1) ? rand(0, 9) : chr(rand(ord(''a''), ord(''z'')));


Las letras son bonitas, los dígitos son feos. ¿Quieres cadenas aleatorias, pero no quieres cadenas al azar "feas"?

Cree un número aleatorio e imprímalo en estilo alfabético (base-26), como los "números" de reservas que dan las aerolíneas.

No hay funciones de conversión de base de propósito general integradas en PHP, hasta donde yo sé, por lo que necesitaría codificar ese bit usted mismo.

Otra alternativa: use uniqid () y elimine los dígitos.

function strip_digits_from_string($string) { return preg_replace(''/[0-9]/'', '''', $string); }

O reemplázalos con letras:

function replace_digits_with_letters($string) { return strtr($string, ''01234567890'', ''abcdefghij''); }