【问题标题】:why my MySQL queries executed before PHP Conditional check?为什么我的 MySQL 查询在 PHP 条件检查之前执行?
【发布时间】:2019-11-24 02:07:48
【问题描述】:

我正在学习创建条件事件,其中在插入数据之前存在 sql checkout 数据,因此它们不会发生冲突。

我尝试在 php 中使用 mysql 行检查,然后在我尝试验证查询是否正确执行之前检查查询是否为空。

在条件满足时也尝试关闭数据库连接,但无论如何它毫无价值。

$user = addslashes(strtolower($usr));
$mail = addslashes(strtolower($mail));
$pass = md5(addslashes($pwd));

$check = $db->query("SELECT EXISTS(SELECT * 
                                   FROM `users`
                                   WHERE LOWER(`username`) = LOWER('$user')
                                      OR LOWER(`email`) = LOWER('$mail'))");

if (!$check) {
    $db->close();
    return false;
} else {
    $sql = "INSERT IGNORE INTO `users` (`username`, `password`, `email`)
                   VALUES ('$user', '$pass', '$mail')";
    $query = $db->query($sql);
    $db->close();
    return true;
}

我希望它在数据为空时执行我的查询,并在数据存在时返回 false。

【问题讨论】:

  • var_dump($check) 给出了什么?您不应使用addslashesmd5。参数化您的查询并使用password_hash(在需要时使用password_verify)。
  • 还要添加到@user3783243 的评论中,这种方法/方法也容易出现竞争条件。如果你想防止重复,你应该在表中添加一个唯一键(也)。
  • @user3783243 它看起来像这样object(mysqli_result)#3 (5) { ["current_field"]=> int(0) ["field_count"]=> int(1) ["lengths"]=> NULL ["num_rows"]=> int(1) ["type"]=> int(0) }
  • “我认为,用户名和电子邮件这两个字段都使用唯一值?对,那你为什么在这里使用 OR 条件?” @devpro 一些应用程序允许使用用户名登录或电子邮件..
  • 完全取决于应用程序。不同的用户可以使用相同的用户名或相同的电子邮件吗?还是只是独特的组合?我会说电子邮件至少应该是唯一的,但同样 - 取决于应用程序的功能和结构。

标签: php mysql conditional-statements


【解决方案1】:

您的主要问题是 $check 将始终是一个真实的值,只要查询永远不会失败。如果查询返回 0 行,它仍然是一个真正的对象。

您应该检查是否有任何返回值。您还可以稍微简化查询,因为 MySQL 不区分大小写,并且您不需要检查结果是否存在。使用准备好的语句,代码看起来像这样

$stmt = $db->prepare("SELECT username FROM users WHERE username = ? OR email = ?");
$stmt->bind_param("ss", $usr, $mail);
$stmt->execute();
$check = $stmt->fetch();
$stmt->close(); 

// True if the user exists 
if ($check) { 
    return false;
} else {
    $stmt = $db->prepare(" INSERT INTO users (username, password, email) VALUES (?, ?, LOWER(?))");
    $stmt->bind_param("sss", $usr, $pass, $mail);
    $stmt->execute();
    $stmt->close();
}

也就是说,您不应该使用 md5() 作为密码,而是使用 password_hash()password_verify()

【讨论】:

  • 请记住,这仍然容易出现竞争条件,假设表中有非唯一键..
  • 公平点 - 你可以使用 INSERT INTO ... ON DUPLICATE KEY UPDATE username=username 或类似的东西,然后检查受影响的行是什么,或者可能是插入的 ID。
  • 确实会。我真的很自以为是,我们还没有看到任何与问题一起发布的表格结构。
【解决方案2】:

你可以像这样改变你的代码

$check = $db->query("SELECT EXISTS(SELECT * FROM `users`
    WHERE LOWER(`username`) = LOWER('$user')
    OR LOWER(`email`) = LOWER('$mail'))");


$check = $conn->query($sql); 
$value = $check->fetch_row()[0];
if($value > 0 ){    
    echo "existed".$value; // you can change accordingly
}else{
    echo "doesn't exist"; // this also
}

因为数据库以 1 表示存在,0 表示不存在,所以 num_row 将始终为 1,这就是为什么我们无法用 num_row 确定存在所以我们必须获取值。

【讨论】:

  • 获取错误Notice: Undefined property: mysqli_result::$num_row
  • 请在您的答案中添加一些解释,以便其他人可以从中学习
  • 尝试更新代码。我也检查了我的数据库。它肯定会运行。
猜你喜欢
  • 2013-03-28
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 2021-03-09
  • 2019-12-27
  • 1970-01-01
相关资源
最近更新 更多