检查条件下是否存在行(PDO,准备???)

时间:2012-10-31 21:43:21

标签: php pdo mysqli

以下代码表示我尝试尝试查找代码中是否存在符合条件的行。它默认为else语句,正确,但如果if语句似乎为true(没有电子邮件发送到ashfjks@sdhja.com),则不能使用'if'语句,并且相反,代码继续进行。这段代码的后半部分主要是为了扩展这种情况。该行只能存在或不存在,所以我不明白为什么它不严格地做一个或另一个。我正在转换为PDO for site secuirty,这就是为什么不是所有人都在PDO中。如果这个问题过于本地化,我很抱歉?

$stmt = $pdo->prepare("SELECT * FROM table WHERE email = ?");
$stmt->execute(array("$email"));
$row3 = $stmt->fetch(PDO::FETCH_ASSOC);

while($row = $stmt->fetch()) {

  if ( ! $row3) {
    // Row3 doesn't exist -- this means no one in the database has this email, allow the person to join
    $query = "INSERT INTO table (username, email, password, join_date) VALUES ('$username', '$email', SHA('$password1'), NOW())";
    mysqli_query($dbc, $query); 
    $query = "SELECT * FROM table WHERE username = '$username'";
    $data2 = mysqli_query($dbc, $query);
  while ($row = mysqli_fetch_array($data2)) {

  $recipent = '' . $row['user_id'] . '';

    $query = "INSERT INTO messages (recipent, MsgTit, MsgR, MsgA, sender, time, readb, reada, MsgCon) VALUES ('$recipent', '$MsgTit', '$MsgR', '$MsgA', '$sender', NOW(), '$readb', '$reada', '$MsgCon')";
    mysqli_query($dbc, $query);

    // Aftermath.
    echo '<p>Your new account has been successfully created. You\'re now ready to <a href="game2.php" target="_blank">log in</a>. After this you should implement basic character-details on your users profile to begin the game.</p>';

    mysqli_close($dbc);
    exit();
  } }  
  else {
    // An account already exists for this email, so display an error message
    echo '<p class="error">An account already exists for this e-mail.</p>';
    $email = "";
  }
}

2 个答案:

答案 0 :(得分:2)

+1来自@Geoff_Montee,但这里还有一些提示:

  • 确保在每次prepare()或execute()之后检查错误。报告错误(但不要将SQL暴露给用户),并正常失败。

  • 请注意,即使您检查了是否存在与$ email匹配的行,也可以在检查后和INSERT之前的短暂时间内创建此行。这是race condition。即使您选择匹配$ email的行,也应该在数据库中使用UNIQUE约束,并在执行INSERT时捕获错误,以防UNIQUE约束因冲突而阻塞插入。

  • SELECT email而不是SELECT *。如果您有电子邮件索引,那么查询运行效率更高,因为它只能检查给定值的索引,而不必在不需要时读取表的所有列。此优化称为仅索引查询

  • 同样使用SELECT user_id代替SELECT *。仅在您确实需要获取所有列时才使用SELECT *

  • Bcrypt is more secure than SHA for hashing passwords.

答案 1 :(得分:2)

您的if语句永远不会被执行。您需要检查返回的行数。这就是你想要的:

注意:我最初使用的是$stmt->rowCount(),但OP表示这对他不起作用。但我很确定该错误的原因来自其他地方。

if (!($stmt = $pdo->prepare("SELECT * FROM table WHERE email = ?"))) {
   //error
}

if (!$stmt->execute(array("$email"))) {
    //error
}
//The $row3 var you had was useless. Deleted that.

$count = 0;

while ($row = $stmt->fetch()) {
    $count++;
}

//The query returned 0 rows, so you know the email doesn't exist in the DB
if ($count== 0) {

    $query = "INSERT INTO table (username, email, password, join_date) VALUES ('$username', '$email', SHA('$password1'), NOW())";

    if (!mysqli_query($dbc, $query)) {
        //error
    }

    $query = "SELECT * FROM table WHERE username = '$username'";

    if (!($data2 = mysqli_query($dbc, $query))) {
        //error
    }

    while ($row = mysqli_fetch_array($data2)) {

        $recipent = '' . $row['user_id'] . '';

        $query = "INSERT INTO messages (recipent, MsgTit, MsgR, MsgA, sender, time, readb, reada, MsgCon) VALUES ('$recipent', '$MsgTit', '$MsgR', '$MsgA', '$sender', NOW(), '$readb', '$reada', '$MsgCon')";

        if (!mysqli_query($dbc, $query)) {
            //error
        }

       // Aftermath.
       echo '<p>Your new account has been successfully created. You\'re now ready to <a href="game2.php" target="_blank">log in</a>. After this you should implement basic character-details on your users profile to begin the game.</p>';

       mysqli_close($dbc);
       exit();
   }
}
//The query did not return 0 rows, so it does exist in the DB
else {
    // An account already exists for this email, so display an error message
    echo '<p class="error">An account already exists for this e-mail.</p>';
    $email = "";
}

你应该完全转换其余的查询以使用PDO。