我是一名学生,这是我第一次编写软件。它是 LAMP 堆栈上的 Web 应用程序,作为该 Web 应用程序的一部分,我编写了以下函数来在创建新用户时与数据库交互:
public function CreateUser($username, $password, $email){
global $DBHandler, $SQLStatement;
$SQLStatement = $DBHandler->prepare("SELECT id FROM users WHERE username = :username AND verified > 0");
$SQLStatement->bindParam(':username', $username);
$SQLStatement->execute();
$check = $SQLStatement->fetch();
if ($check['id']){
return 2;
}else{
$SQLStatement = $DBHandler->prepare("SELECT id FROM users WHERE email = :email AND verified > 0");
$SQLStatement->bindParam(':email', $email);
$SQLStatement->execute();
$check = $SQLStatement->fetch();
if ($check['id']){
return 3;
}else{
/* Edited out code that generates a random verification code, a random salt, and hashes the password. */
$SQLStatement = $DBHandler->prepare("INSERT INTO users (username, email, passwordhash, salt, verifycode) VALUES (:username, :email, :passwordhash, :salt, :verifycode)");
$SQLStatement->bindParam(':username', $username);
$SQLStatement->bindParam(':email', $email);
$SQLStatement->bindParam(':passwordhash', $passwordhash);
$SQLStatement->bindParam(':salt', $salt);
$SQLStatement->bindParam(':verifycode', $verifycode);
$SQLStatement->execute();
return 1;
}
}
}
$DBHandler 在其他地方作为 PHP 数据对象启动。
它遵循以下基本步骤:
- 查询数据库以查看是否有人已经验证了具有所需用户名的帐户。
- 如果用户名可用,请执行另一个查询并对电子邮件进行相同的检查。
- 如果用户名和电子邮件都可用,则生成验证码、加盐、散列密码、执行第三次查询以将所有内容写入数据库,然后返回 1(表示成功)。
这个想法是,在您的帐户得到验证(已验证 = '1')之前,不会保留用户名和电子邮件。如果您单击通过电子邮件发送的验证链接,则在其他地方有一个脚本会将您的已验证列更改为“1”。
我的第一个问题是这样的:
人 A 提出了用户名“Lorem”,而人 B 有一个未经验证的帐户,该帐户也提出了用户名“Lorem”。是否可以按以下顺序执行查询?
- 人员 A 的脚本确定用户名“Lorem”未由经过验证的用户使用
- 人 B 的脚本使用用户名“Lorem”验证他们的帐户
- 人员 A 的脚本使用用户名“Lorem”创建其未经验证的帐户
我的第二个问题是:
是否可以将此脚本中的 3 个查询组合成 1 个查询,使用 SQL 而不是 PHP 表示的相同 if/else 逻辑,如果是这样,这会提高性能和/或防止上述情况发生吗?