Avatar billede nemlig Professor
26. oktober 2007 - 14:11 Der er 14 kommentarer og
1 løsning

Problemer med unikke randomnumre

Hej.
Jeg har et system, hvor jeg opretter nogle lejeaftaler.
For hver lejeaftale oprettes en post i Mysql, og på hver post gemmes et unikt nr. som anvendes til unikke URL.
Nu har jeg været udsat for, at det samme 20-cifrede nr. er oprettet til flere poster. Det burde vel ske 1 gang ud af mange milliarder. Der må derfor været noget galt i koden:
Håber der er en, som vil kigge på koden. Jeg er godt klar over, at jeg blot kan lave et tjek i MySQL om koden er oprettet i forvejen, og hvis ja, så må den generere en ny:
Koden ser sådan her ud:

//Her fastsættes Unikt nr.
    $a = array( "A","B","C","D","E","F","G","H","I",
                            "K","L","M","N","O","P","Q","R","S",
                            "T","U","V","X","Y","Z","a","b","c",
                            "d","e","f","g","h","i","k","l","m",
                            "n","o","p","q","r","s","t","u","v",
                            "x","y","z",);
   
    $raw = "";
    $length = 20;
    $no = 5;
   
    for($i = 1;$i <= $length ; $i++)
    {
        $raw .= $a[rand(0,47)];
    }
   
    for($i = 1;$i <= $no;$i++)
    {
        $raw{rand(0,$length)} = rand(0,9);
    }
Avatar billede nielle Nybegynder
26. oktober 2007 - 14:27 #1
I PHP versioner før 4.0 er det nødvendigt at give et seed til rand:

http://dk2.php.net/manual/da/function.srand.php
Avatar billede nielle Nybegynder
26. oktober 2007 - 14:27 #2
Version 4.2
Avatar billede nemlig Professor
26. oktober 2007 - 14:43 #3
Siden ligger hos Web10.dk og de anvender php version 5.2
Avatar billede neoman Novice
26. oktober 2007 - 14:56 #4
Prøv at kigge på folks bemærkninger til http://dk2.php.net/rand  - den automatiske seeding er måske ikke helt perfekt.
Avatar billede nemlig Professor
26. oktober 2007 - 15:08 #5
Jeg forstår det ikke helt, men jeg løser det vel bare med at lave et tjek i min MySQL om nummeret er genereret i forvejen:
Jeg er dog lidt usikker på hvordan. Det skal vel laves med en While-statement.... Håber på lidt hjælp.
Vil mene, at denne kode, tjekker om der er enslydende i forvejen:
$sql = "SELECT * FROM tabel WHERE xid= '".$raw."'";
$res = database($sql);
if (mysql_num_rows($res) == 0) { //så er nummeret OK - ellers skal den prøve igen.

Men hvordan opsætter jeg while eller hvad der nu skal til, for at den kører løkken igen.
Avatar billede nemlig Professor
26. oktober 2007 - 15:22 #6
Eller forslag til, hvordan korrekt unikt nr. kan defineres, modtages også gerne.
Avatar billede nemlig Professor
26. oktober 2007 - 16:01 #7
Er det noget i denne retning:

$x=1;
while($x < 2) {
    //Her fastsættes $aftaleid
    $a = array( "A","B","C","D","E","F","G","H","I",
                            "K","L","M","N","O","P","Q","R","S",
                            "T","U","V","X","Y","Z","a","b","c",
                            "d","e","f","g","h","i","k","l","m",
                            "n","o","p","q","r","s","t","u","v",
                            "x","y","z",);
   
    $raw = "";
    $length = 20;
    $no = 5;
   
    for($i = 1;$i <= $length ; $i++)
    {
        $raw .= $a[rand(0,47)];
    }
   
    for($i = 1;$i <= $no;$i++)
    {
        $raw{rand(0,$length)} = rand(0,9);
    }

$sql = "SELECT * FROM kalender_aftale WHERE xid= '".$raw."'";
$res = database($sql);   
if (mysql_num_rows($res) == 0)
    {
        $x = 2;
    } else {
        $x = 1;
    }
}
Avatar billede nielle Nybegynder
26. oktober 2007 - 17:03 #8
Burde virke. Personligvt viulle jeg nok vælge at modulisere koden en smule:

function RandomCode() {
    $codeLength = 20;
    $no = 5;

    $a = array("A","B","C","D","E","F","G","H","I",
        "K","L","M","N","O","P","Q","R","S",
        "T","U","V","X","Y","Z","a","b","c",
        "d","e","f","g","h","i","k","l","m",
        "n","o","p","q","r","s","t","u","v",
        "x","y","z");

    $code = "";

    for ($i = 0; $i < $codeLength ; $i++)
    {
        $idx = rand(0, count($a)-1);
        $code .= $a[$idx];
    }
   
    for ($i = 0; $i < $no; $i++)
    {
        $idx = rand(0, $codeLength);
        $code{$idx} = rand(0, 9);
    }

    return $code;
}

$done = false;
while (! $done) {
    $code = RandomCode();

    $sql = "SELECT * FROM kalender_aftale WHERE xid = '$code'";
    $res = database($sql);
    if (mysql_num_rows($res) == 0)
        $done = true;
}
Avatar billede nemlig Professor
26. oktober 2007 - 17:17 #9
OK - Super Nielle. Det skal prøves i aften.
Avatar billede dkfire Nybegynder
26. oktober 2007 - 18:29 #10
Tror også det vil hjælpe dig, hvis du laver dit felt, som indeholder nummeret, unikt.
Avatar billede nemlig Professor
26. oktober 2007 - 19:59 #11
dkfire: Det er jeg opmærksom på. Men jeg vil hellere have, at systemet ikke stopper, fordi der kommer en MySQL-fejl, hvorfor jeg også vil lave et tjek om nummeret eksisterer i forvejen, og hvis ja - så dan et nyt nr.

Nielle: Du har lige hjulpet mig i en anden tråd, og jeg kan se i de eksisterende poster, at samme nummer optræder 3 gange. Der er altså tale om ét bestemt nr.

Så har jeg lige et spørgsmål til den kode, du foreslår ovenfor.
Kan jeg risikere, at systemet kommer til at køre i ring, fordi den vil generere den samme kode?
Avatar billede nielle Nybegynder
26. oktober 2007 - 20:01 #12
Nej, det vil ikke ske :^)
Avatar billede nemlig Professor
26. oktober 2007 - 20:09 #13
Nielle: Så siger jeg tusind tak for hjælpen - det fungerer som det skal.
Send venligst et svar. :-)
Avatar billede nielle Nybegynder
26. oktober 2007 - 20:12 #14
En alternativ måde at løse problemet på, er faktisk at gøre feltet unikt og så have en løkke som prøver igen og igen indtil at der ikke kommer en SQL fejl.
Avatar billede nemlig Professor
26. oktober 2007 - 20:16 #15
Jeps - men jeg synes det her er en OK-løsning.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester