Frage

Ich möchte eine eindeutige ID schaffen, sondern uniqid() etwas wie '492607b0ee414' gibt. Was ich möchte, ist etwas Ähnliches, was tinyurl gibt: '64k8ra'. Je kürzer, desto besser. Die einzigen Voraussetzungen sind, dass es keine offensichtlichen haben sollte, und dass es als eine scheinbar zufällige Folge von Zahlen aussieht schöneres soll. Briefe werden über Zahlen bevorzugt und im Idealfall wäre es nicht gemischt Fall sein. Da die Anzahl der Einträge wird nicht so viele (bis zu 10000 oder so) das Risiko einer Kollision ist nicht ein sehr großer Faktor.

Irgendwelche Vorschläge geschätzt.

War es hilfreich?

Lösung

Machen Sie eine kleine Funktion, die zufälligen Buchstaben für eine bestimmte Länge zurückgibt:

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

Dann sollten Sie anrufen, dass bis es einzigartig, in Pseudo-Code je nachdem, wo Sie diese Informationen speichern würde:

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

Sie möchten vielleicht auch die Buchstaben stellen Sie sicher, nicht ein Wort in einem Dictionnary bilden. Kann es das ganze Englisch Dictionnary oder nur ein schlechtes Wort Dictionnary sein, die Dinge zu vermeiden, ein Kunde von bad-Geschmack finden würde.

EDIT: Ich würde auch dies nur sinnvoll hinzufügen, wenn, wie Sie es nutzen wollen, ist es nicht für eine große Menge von Produkten, da diese ziemlich die mehr Kollisionen langsam bekommen könnten Sie bekommen (eine ID bereits in der Tabelle bekommen) . Natürlich, werden Sie eine indizierte Tabelle wollen, und Sie werden die Anzahl der Buchstaben in der ID-Kollision zu vermeiden optimieren wollen. In diesem Fall mit 6 Buchstaben, dann würden Sie 26 ^ 6 = 308915776 möglich eindeutige IDs haben (minus Schimpfwörter), die für Ihren Bedarf an 10000 genug sein sollte.

EDIT: Wenn Sie eine Kombination aus Buchstaben und Zahlen möchten, können Sie den folgenden Code verwenden:

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

Andere Tipps

@gen_uuid () durch gord.

preg_replace bekam einige bösen utf-8 Probleme, die die uid somtimes verursacht "+" oder "/" enthalten. Um dies zu umgehen, müssen Sie explizit das Muster utf-8 machen

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

Hatte mir eine ganze Weile, dass zu finden, vielleicht spart es jemand anderen Kopfschmerzen

Sie können, dass mit weniger Code erreichen:

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

Ergebnis (Beispiele):

  • cjnp56brdy
  • 9d5uv84zfa
  • ih162lryez
  • ri4ocf6tkj
  • xj04s83egi

Es gibt zwei Möglichkeiten, um eine zuverlässig eindeutige ID zu erhalten: Machen Sie es so lange und variabel, dass die Chancen einer Kollision spektakulär klein sind (wie bei einer GUID) oder speichern Sie alle generierten IDs in einer Tabelle für die Suche (entweder im internen Speicher oder in einem DB oder eine Datei) Eindeutigkeit bei der Erzeugung zu überprüfen.

Wenn Sie wirklich fragen, wie Sie eine solche kurze Schlüssel erzeugen und garantieren seine Einzigartigkeit ohne irgendeine Art von Dublettenprüfung, die Antwort ist, können Sie nicht.

Hier ist die Routine, die ich für zufällige base62s beliebiger Länge verwenden ...

Beim gen_uuid() gibt Strings wie WJX0u0jV, E9EMaZ3P etc.

Standardmäßig Diese 8 Ziffern liefert, damit ein Raum von 64 ^ 8 oder etwa 10 ^ 14, das ist oft genug Kollisionen sehr selten zu machen.

Für eine größere oder kleinere Zeichenfolge, übergeben in $ len, wie gewünscht. Keine Begrenzung in der Länge, wie ich bis zufrieden anhängen [bis zu Sicherheitsgrenze von 128 Zeichen, die entfernt werden können].

Hinweis, verwenden Sie ein zufälliges Salz innen die md5 [oder SHA1, wenn Sie bevorzugen], so dass es leicht reverse-engineered kippe werden.

Ich habe keine zuverlässige Base62 Konvertierungen im Web finden, damit dieser Ansatz von Zeichen aus dem base64 Ergebnis Strippen.

Verwenden Sie frei unter BSD-Lizenz, genießen,

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

Wirklich einfache Lösung:

Machen Sie die eindeutige ID mit:

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

wieder den ursprünglichen Wert Erhalten Sie:

intval($str,36);

Kann nicht Kredit für diese nehmen, wie es von einer anderen Stack-Überlauf Seite, aber ich dachte, die Lösung war so elegant und genial, dass es wert war, das auf diesen Thread zu kopieren über für Menschen verweisen.

Sie könnten die Id verwenden und es nur Basis-36 konvertieren Nummer, wenn Sie es hin und her konvertieren möchten. Kann mit einer ganzen Zahl ID für jede Tabelle verwendet werden.

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

Intelligente Menschen können es wahrscheinlich herausfinden, mit genug id Beispiele. Lassen Sie sich nicht diese Unklarheit Sicherheit ersetzen lassen.

Ich kam mit dem, was ich denke, eine ziemlich coole Lösung ist dies ohne eine Einzigartigkeit Prüfung zu tun. Ich dachte, ich für zukünftige Besucher teilen würde.

Ein Zähler ist eine wirklich einfache Möglichkeit, Eindeutigkeit zu gewährleisten, oder wenn Sie verwenden auch eine Datenbank ein Primärschlüssel garantiert Einzigartigkeit. Das Problem ist, es sieht schlecht aus und und könnten anfällig sein. Also nahm ich die Reihenfolge und purzeln sie mit einer Chiffre auf. Da die Chiffre rückgängig gemacht werden kann, weiß, dass ich jede ID eindeutig ist, während immer noch zufällig erscheinen.

Es ist Python nicht php, aber ich den Code hier hochgeladen: https://github.com/adecker89/Tiny-Unique-Identifiers

Buchstaben sind hübsch, Ziffern hässlich sind. Sie wollen zufällige Zeichenfolge, aber nicht „hässlich“ zufällige Zeichenfolge mögen?

Erstellen Sie eine Zufallszahl und drucken Sie es in alpha-style ( base-26 ), wie die Reservierung "Zahlen", dass die Fluggesellschaft geben.

Es gibt keine Allzweck-Funktionen Basis Umwandlung in PHP gebaut, so weit ich weiß, so würden Sie Code benötigen, die sich wenig.

Eine andere Alternative:. Verwenden uniqid() und loszuwerden, die Ziffern

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

oder ersetzen sie durch Buchstaben:

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

Sie können es auch tun, wie folgt:

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

Sie können das tun ohne unreinen / costy Sachen wie Schleifen, String Verkettungen oder mehrere Aufrufe rand (), in einem sauberen und einfach zu lesen. Außerdem ist es besser mt_rand() zu verwenden:

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

Wenn Sie den String benötigen die genaue Länge in jedem Fall zu haben, nur Pad die Hex-Zahl mit Nullen:

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

Die „theoretische backdraw“ ist, dass Sie auf PHPs Fähigkeiten begrenzt sind - aber das ist mehr eine philosophische Frage in diesem Fall;) Lassen Sie uns durch sie gehen sowieso:

  • PHP ist dadurch begrenzt, was es als Hex-Zahl macht es so darstellen kann. Dies würde auf einem 32-Bit-System $length <= 8 mindestens , wo PHPs Beschränkung hierfür sollte 4.294.967.295 sein.
  • PHPs Zufallszahlengenerator hat auch ein Maximum. Für mt_rand() mindestens auf einem 32-Bit-System, sollte es 2.147.483.647 sein
  • So können Sie theoretisch zu 2.147.483.647 IDs beschränkt.

Kommen zu dem Thema zurück - die intuitiven do { (generate ID) } while { (id is not uniqe) } (insert id) hat auch einen Nachteil und einen möglichen Fehler, die Sie gerade in der Dunkelheit fahren könnten ...

Nachteil: Die Validierung ist pessimistisch. Tun es wie folgt immer in der Datenbank eine Prüfung erfordert. genug Schlüsselraum (zum Beispiel Länge von 5 für Ihre 10k Einträge) wird ziemlich unwahrscheinlich Ursache Kollisionen, so oft, wie es sein könnte vergleichbar weniger ressourcenaufwendig nur versuchen, die Daten zu speichern, und versuchen Sie es erneut nur bei ein eindeutiger Schlüssel Fehler.

Flaw: Benutzer A ruft eine ID, die noch nicht genommen prüft wird. Dann wird der Code versuchen, die Daten einzufügen. Aber in der Zwischenzeit Benutzer B trat in die gleiche Schleife und leider ruft die gleiche Zufallszahl, weil Benutzer A noch nicht gespeichert ist, und diese ID war noch frei. Nun speichert das System entweder Benutzer B oder Benutzer A , und wenn den zweiten Benutzer zu speichern versuchen, es bereits der andere in der Zwischenzeit -. Mit derselben ID

Sie müßten diese Ausnahme in jedem Fall zu handhaben und das Einsetzen mit einer neu erstellten ID erneut versuchen zu müssen. Addiert man diese während der pessimistischen Kontrolle Schleife zu halten (die Sie neu eingeben müßten) wird in ziemlich hässlich und schwer führt Code zu folgen. Glücklicherweise ist die Lösung dieses Problems ist die gleiche wie die, die zum Nachteil: Gehen Sie einfach für sie an erster Stelle und versuchen, die Daten zu speichern. Im Fall eines Fehlers UNIQUE KEY nur mit einer neuen ID wiederholen.

Nehmen Sie einen lookt in diesem Artikel

Es wird erklärt, wie kurze eindeutige IDs von Ihrem BDD-IDs zu erzeugen, wie YouTube der Fall ist.

Eigentlich ist die Funktion in dem Artikel sehr im Zusammenhang mit , die eine Anzahl von einer Basis in einer anderen umwandelt (aber nur bis zur Basis 36).

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

Wenn Sie dies tun wie eine längere Version von einzigartiger Id Verwendung dieses:
$ Uniqueid = SHA1 (md5 (time ()));

Best Antwort noch: Kleinste Unique "Hash Like" String Gegeben Einzigartige Datenbank-ID - PHP-Lösung , No Third Party Bibliotheken Erforderlich.

Hier ist der Code:

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

}

?>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top