0

以下のコードは、コードで指定された基準で行が存在するかどうかを調べようとした試みを示しています。デフォルトはelseステートメントですが、ifステートメントが真のように見える場合( ashfjks@sdhja.comとして電子メールが送信されていない場合)、「if」ステートメントでは機能せず、代わりにコードが続行されます。このコードの後半部分は、主に状況を拡張するためのものです。行は存在するか存在しないかしかできないため、厳密にどちらか一方を実行していない理由がわかりません。私はサイトのセキュリティのために PDO に変換しています。そのため、まだすべてが 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 = "";
  }
}
4

2 に答える 2

2

@Geoff_Monteeから回答するには+1しますが、さらにいくつかのヒントがあります。

  • すべてのprepare()またはexecute()の後に必ずエラーをチェックしてください。エラーを報告し(ただし、SQLをユーザーに公開しないでください)、正常に失敗します。

  • $ emailに一致する行の存在を確認した場合でも、そのような行は、確認してからINSERTを実行する前の短い時間で作成される可能性があることに注意してください。これは競合状態です。$ emailに一致する行をSELECTする場合でも、データベースでUNIQUE制約を使用し、競合のためにUNIQUE制約が挿入をブロックした場合に備えて、INSERTを実行するときにエラーをキャッチする必要があります。

  • SELECT emailの代わりにSELECT *。電子メールにインデックスがある場合、クエリは、必要のないときにテーブルのすべての列を読み取る必要がなく、指定された値のインデックスをチェックするだけでよいため、より効率的に実行されます。この最適化は、インデックスのみのクエリと呼ばれます。

  • 同様に、SELECT user_idの代わりに使用しSELECT *ます。SELECT *本当にすべての列をフェッチする必要がある場合にのみ使用してください。

  • パスワードのハッシュに関しては、BcryptはSHAよりも安全です。

于 2012-10-31T21:57:03.083 に答える
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を使用する必要があります。

于 2012-10-31T21:57:42.677 に答える