I am creating a random user ID, but I would like to check if the ID already has been used (very unlikely but the chances are there), but somehow this doesn't work. When I look in the database, there is no random character string in the account_id field. Do I call the functions in a wrong way?

function genRandomString() {
    $length = 40;
    $characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";    
    for ($p = 0; $p < $length; $p++) {
        $string .= $characters[mt_rand(0, strlen($characters))];
    }
    return $string;
}

function createID() {
    $cl_id = 'h_u_'.genRandomString();
}   

createID();

$sql_query="SELECT * FROM accounts WHERE account_id = :cl_id";
$statement = $conn->prepare($sql_query);
$statement->bindParam(':cl_id', $cl_id, PDO::PARAM_STR);    
if ($statement->execute() && $row = $statement->fetch())
    {
        createID();
    }

$conn->exec("INSERT INTO accounts SET  
            account_id='$cl_id' ,
            name='$_POST[name]' ,
            email='$_POST[email]' ");   
有帮助吗?

解决方案

$cl_id is a local variable in createID() function , you need to return your value to your global code ...

function createID() {
return $cl_id = 'h_u_'.genRandomString();
}   

you need to check $id in the main code

$id = createID();
$sql_query="SELECT * FROM accounts WHERE account_id = '".$cl_id."'";
$statement = $conn->prepare($sql_query);

其他提示

1 . You missed to return $c_id in createID(). Change it to:

function createID() {
    return 'h_u_'.genRandomString();
}

$cl_id = createID();

2 . You could use good old uniqid() instead of your custom genRandomString().

This would lead to something simpler like:

function createID() {
    return 'h_u_'.uniqid();
}

$cl_id = createID();

3 . You'll have to change the if in the database related code to a loop (have a look at my example below)

4 . Your insert query uses unverified $_POST vars. This is highly prone to SQL Injections. If your Database library supports server side prepared statements you should use them and you can feel secure because data is being kept separate from the query syntax. If you are using PHP with MySQL this is the case.

If you are not using server side prepared statements you should escape any $_POST data used in the query by using mysql_real_escape_string() or something like this. In the following example I'm assuming that you are using PHP with MySQL and thatswhy I use a prepared statement.

Taking all this in account may result in a finished script like this:

$sql_query="SELECT * FROM accounts WHERE account_id = :cl_id";
$statement = $conn->prepare($sql_query);
$maxtries = 3; // how many tries to generate a unique id?

for($i = 0; $i < $maxtries; $i++) {
    $cl_id = uniqid(); // create a 'unique' id

    $statement->bindParam(':cl_id', $cl_id, PDO::PARAM_STR);    
    if (!$statement->execute()) {
        die('db error');
    }

    $row = $statement->fetch();
    if($row) {
        continue;
    }
    break;
}

// if a unique id couldn't get generated even
// after maxtries, then pigs can fly too :)
if($i === $maxtries) {
    die('maximum number of tries reached. pigs can fly!');
}

// You should use a prepared statement for the insert to prevent from
// SQL injections as you pass $_POST vars to the query. You should further 
// consider to validate email address and the name!
$name = $_POST['name'];
$email = $_POST['email'];

$insert_query = '
  INSERT INTO accounts SET 
    account_id = :account_id,
    name = :name,
    email = :email'; 

$insert_statement = $conn->prepare($insert_query);
$insert_statement->bindParam(':account_id', $cl_id, PDO::PARAM_STR);
$insert_statement->bindParam(':name', $name, PDO::PARAM_STR);
$insert_statement->bindParam(':account_id', $email, PDO::PARAM_STR);

if (!$insert_statement->execute()) {
    die('db error');
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top