Php kısa benzersiz kimliği

12 Cevap php

Ben benzersiz bir kimliği oluşturmak istiyorum ama uniqid() '492607b0ee414' gibi bir şey veriyor. Ne ben istiyorum tinyurl verir ne benzer bir şey: '64k8ra'. Kısa, daha iyi. Sadece gereksinimleri bariz bir düzen var ve bu sayıların rasgele gibi görünen bir dizisi daha güzelsin gerektiğini de vardır. Harfler sayılar tercih edilir ve ideal karışık durum olmaz. Girişlerin sayısı (10.000 kadar kadar) birçok olmayacak gibi çarpışma riskinin büyük bir faktör değildir.

Herhangi bir öneriniz takdir.

12 Cevap

Belirli bir uzunlukta rasgele harfler döndüren küçük bir işlev yapmak:

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

Sonra bu eşsiz kadar, sözde-kod size bu bilgileri saklamak istiyorum nereye bağlı olduğunu aramak isteyeceksiniz:

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

Ayrıca harfler bir dictionnary bir kelime oluşturmayan emin olmak isteyebilirsiniz. Bir müşteri kötü tat bulur bütün ingilizce dictionnary veya şeyleri önlemek için sadece bir kötü kelime dictionnary olabilir.

EDIT: bunu kullanmak niyetinde olarak, bu öğeler büyük bir miktar için değil, eğer bu güzel (tablonun zaten bir kimliği alma) olsun daha çarpışmaları yavaş alabilir, çünkü ben de bu sadece mantıklı eklersiniz. Tabii ki, dizinlenmiş bir tablo isteyeceksiniz ve çarpışmayı önlemek için kimliği harflerin sayısını oynamak isteyeceksiniz. Bu durumda, 6 harf ile, 10000 ihtiyacı için yeterli olmalıdır 26 ^ 6 = 308.915.776 mümkün benzersiz kimlikler (eksi kötü sözler) olurdu.

EDIT: If you want a combinations of letters and numbers you can use the following code:

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

@ GÖRH () tarafından gen_uuid.

preg_replace got some nasty utf-8 problems, which causes the uid somtimes to contain "+" or "/". To get around this, you have to explicitly make the pattern 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);
}

Belki de bu, o bulmak için bana oldukça zaman aldı başkası bir baş ağrısı kaydeder

Bir güvenilir benzersiz bir kimliği elde etmek için iki yol vardır: Make it bir çarpışma şansı (bellekte veya bir DB ya (bir GUID gibi) olağanüstü küçük ya da arama için bir tablodaki tüm oluşturulan kimliklerini saklamak o kadar uzun ve değişken ya da bir dosya) nesil üzerine benzersizliğini doğrulamak için.

Eğer gerçekten böyle kısa bir anahtar oluşturmak ve yinelenen kontrol çeşit olmadan onun benzersizliğini garanti nasıl soruyorsun, cevap yapamazsın, olduğunu.

Gerçekten basit bir çözüm:

Ile benzersiz kimliği olun:

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

Tekrar orijinal değerini alın:

intval($str,36);

Başka bir yığın taşması sayfasından olduğu gibi bunun için kredi almak, ama çözüm bu başvuran kişiler için bu konu üzerinde kopyalama değdi o kadar zarif ve harika olduğunu düşündüm olamaz.

Burada herhangi bir uzunlukta rasgele base62s için kullanmak rutin bulunuyor ...

Arayan gen_uuid() WJX0u0jV, E9EMaZ3P vb dizeleri döndürür

By default this returns 8 digits, hence a space of 64^8 or roughly 10^14, this is often enough to make collisions quite rare.

Istediğiniz gibi bir büyük veya daha küçük dize için, $ len geçmektedir. Uzunluğunda sınırı yok, [kaldırılabilir 128 karakter güvenlik sınırı, kadar] memnun kadar ekleme gibi.

Kolayca tersine mühendislik olamaz yani, [ya da isterseniz sha1] rastgele bir tuzu inside md5 kullanın, unutmayın.

Ben base64 sonucundan karakter sıyırma dolayısıyla bu yaklaşım, web üzerinde herhangi bir güvenilir base62 dönüşüm bulamadık.

Use freely under BSD licence, enjoy,

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);
}

Sen kimliği kullanmak ve sadece ileri ve geri dönüştürmek istiyorsanız bu temel-36 numara çevirebiliriz. Bir tamsayı kimliği ile herhangi bir tablo için kullanılabilir.

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

Akıllı insanlar muhtemelen yeterli id ​​örneklerle anlamaya olabilir. Bu bilinmezlik güvenlik yerine izin vermeyin.

Ben bir teklik onay olmadan bunu oldukça serin bir çözüm olduğunu düşünüyorum ne ile geldi. Ben herhangi bir gelecek ziyaretçiler için paylaşmak düşündüm.

Bir sayaç teklik garanti etmek gerçekten kolay bir yol ya da bir veritabanı kullanarak eğer bir birincil anahtar da tekliği garanti. Sorun kötü görünüyor ve ve savunmasız olabilir olduğunu. Yani dizisini aldı ve bir şifre ile o kadar karışık. Şifre ters olabilir, çünkü ben yine rastgele görünen ise her id benzersiz olduğunu biliyorum.

It's python not php, but I uploaded the code here: https://github.com/adecker89/Tiny-Unique-Identifiers

Letters are pretty, digits are ugly. You want random strings, but don't want "ugly" random strings?

Rezervasyon "numaralar" havayolları vermek gibi, rastgele bir sayı oluşturun ve alfa-style (base-26) yazdırın.

Orada PHP yerleşik hiçbir genel amaçlı temel dönüşüm işlevleri bildiğim kadarıyla,, bu yüzden kendinizi biraz kod gerekiyordu.

Başka bir alternatif: () uniqid kullanımı ve rakamlardan kurtulmak.

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

Veya harf ile değiştirin:

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

Bunu yapabilirsiniz döngüler, String bitiştirmelerini veya temiz ve okunması kolay bir şekilde rand () için birden fazla görüşme gibi without kirli / costy şeyler. Ayrıca, kullanımı daha iyidir mt_rand():

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

Eğer herhangi bir durumda tam uzunluğuna sahip dize gerekiyorsa, sadece ped sıfır ile onaltılık sayı:

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

"Teorik backdraw" Eğer PHPs yetenekleri sınırlı olduğu, - ama bu en zaten bunun üzerinden gidelim ;) bu durumda daha felsefi bir konudur:

  • PHP bu gibi yaparken bir onaltılık sayı olarak temsil edebilir ne de sınırlıdır. Bu, bu PHPs için sınırlama 4.294.967.295 olması gereken bir 32 bit sistemi üzerinde $length <= 8 at least olacaktır.
  • PHPs rasgele sayı üreteci de bir maksimum vardır. mt_rand() at least 32bit sistemde, bu 2.147.483.647 olması gerekmektedir
  • Yani teorik olarak 2.147.483.647 kimlikleri ile sınırlıdır.

Konuya geri geliyor - sezgisel do { (generate ID) } while { (id is not uniqe) } (insert id) bir dezavantajı ve karanlığa düz sürücü olabilir, olası bir kusur vardır ...

Drawback: doğrulama karamsar. Bu gibi yapmaya always veritabanının bir kontrol gerektirir. (Senin 10k girişleri için 5 örnek uzunluğu için) yeterli keyspace olacak olması oldukça muhtemel nedeni çarpışmalar sık ​​sık, o comparably daha az kaynak sadece sadece bir durumunda verileri saklamak ve yeniden denemek için denemek için alıcı olabileceği gibi UNIQUE KEY hatası.

Flaw: User A henüz alınmamıştır olarak doğrulanmış olur bir kimliği alır. Ardından kod veri eklemek için çalışacağız. Ama bu arada, User B aynı döngüye girdi ve User A henüz depolanır ve bu kimliği hala özgür değildi, çünkü ne yazık ki, aynı rasgele sayı, alır. Şimdi sistemi depolar ya User B veya User A, ve ikinci kullanıcı saklamak için çalışırken, zaten arada diğer bir var - aynı ID'ye sahip.

Herhangi bir durumda bu istisnayı işlemek ve yeni oluşturulan kimliği ile yeniden denemek ekleme gerekir gerekir. (Yeniden girmeniz gerekir ki) kötümser kontrol döngü korurken bu ekleme oldukça çirkin ve kod takip etmek zor neden olur. Fortunately the solution to this is the same like the one to the drawback: Sadece ilk etapta bunun için gidin ve verileri depolamak için deneyin. UNIQUE KEY hata durumunda sadece yeni kimliği ile yeniden deneyin.

Ayrıca çalıştırılarak gibi yapabilirsiniz:

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;
    }

Bu makalede bir lookt atın

Youtube yaptığı gibi, sizin bdd kimlikleri kısa benzersiz kimlikleri oluşturmak için nasıl açıklar.

Aslında makalede fonksiyon php function base_convert hangi bir tabandan başka bir numara çevirir (ama sadece 36 tabanına kadar olan) çok ilgilidir.

Daha az kod ile elde edebilirsiniz:

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

Sonuç (örnekler):

  • cjnp56brdy
  • 9d5uv84zfa
  • ih162lryez
  • ri4ocf6tkj
  • xj04s83egi