开发者

Repeating a function

This is a follow-up question to a question I posted here.

I am using the following code to give users a unique id:

function NewGuid() { 
    $s = strtoupper(uniqid(rand(),true)); 
    $guidText = substr($s,0,8) . '-' . substr($s开发者_如何学JAVA,8,4) . '-' . substr($s,12,4). '-' . substr($s,16,4). '-' . substr($s,20); return $guidText; 
} 

$Guid = NewGuid();
echo $Guid;

$alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';

function base_encode($num, $alphabet) { 
    $base_count = strlen($alphabet); 
    $encoded = '';

    while ($num >= $base_count) {
        $div = $num/$base_count;
        $mod = ($num-($base_count*intval($div)));
        $encoded = $alphabet[$mod] . $encoded;
        $num = intval($div);
    }

    if ($num) $encoded = $alphabet[$num] . $encoded;
    return $encoded;    
}

function base_decode($num, $alphabet) { 
    $decoded = 0;
    $multi = 1;

    while (strlen($num) > 0) {
        $digit = $num[strlen($num)-1];
        $decoded += $multi * strpos($alphabet, $digit);
        $multi = $multi * strlen($alphabet);
        $num = substr($num, 0, -1);
    }

    return $decoded;
}

echo base_encode($Guid, $alphabet);

So, if a id that is generated is already in use, i want this code to be able to repeat until a completely new id is generated and entered into the database. IN addition i am new to programming, so please feel free to elaborate ;)

Any thoughts? Thanks.


Super easy.

You have 3 functions.

One - main generate guid function.
Two - Sub generate guid function.
Three - Sub insert guid function.

Sub generate function:
Does the actual generation, returns a guid.

Sub insert function:
Attempts to insert guid into the database. Returns false/null on failure. True/data on success.

Main function:
In a loop:
Call subfunction to get a guid.
Call subfunction to insert in the database where the guid is a unique or primary key.
On failure, restart the loop.
Success exits the loop and returns the guid.

Example:

function GetGuid()
{
    do
    {
        $guid = GenerateGuid();
    } while (!InsertGuid($guid));
    return $guid;
}

function GenerateGuid()
{
    // do your stuff here.
    return $guid;
}

function InsertGuid($guid)
{
    $sql = 'INSERT INTO `guid_table` (`guid`) VALUES ('$guid')';
    $connection = //do sql connect here;
    return // do sql execution here which will return false/null on failure;
}


function randr($j = 8){
$string = "";
    for($i=0;$i < $j;$i++){
        srand((double)microtime()*1234567);
        $x = mt_rand(0,2);
        switch($x){
            case 0:$string.= chr(mt_rand(97,122));break;
            case 1:$string.= chr(mt_rand(65,90));break;
            case 2:$string.= chr(mt_rand(48,57));break;
        }
    }
return $string; 
}

    do{
    $id = randr();
    $check = mysql_query("SELECT uniq FROM users WHERE uniq = '$id'");
    }while(mysql_num_rows($check) != 0);

Think about this.


I have to upgrade/fix a system that's written similarly to the way you code, and I gotta tell you, I've really grown to hate the original programmer.

Think about what you're doing for a sec, if another user creates an account between when you ask if the guid is valid (and get back yes) and when you actually insert the row, you can still have collisions. That's beyond horrible...

But the guys that made the database programs thought of this and offer you a painless alternative: identity columns. They provide 3 major advantages:

  • guaranteed to be unique (or the insertion fails)
  • they're automatically made into a primary key
  • the database generates them for you

To use them, make your ID column to be an identity column, and when you do your insert, write it like this:

insert into users (name, passwordhash, extrastuff) 
values (@name, @passwordhash, @extrastuff);
select @@identity -- or ident_current() for mysql

And you get back the user id generated for you for further processing. This is all done simultaneously, no matter how many users are trying this at the same time.


I built similar code before, I typically start with a null variable, and I do while ($variable == null) { }

inside the while, I create the new code check it against the database and if it doesn't exist yet, I set $variable = $new_code (which will break the while) and then proceed accordingly.

Additionally, I log any collisions that may occur

hope this helps


May be , a slight different approach

i would move my generation logic inside a stored procedure and ask database to generate a unique sequence like in oracle.

This way , i would be able to avoid numerous trips to check the number is unique or not.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜