5 Stimmen

Kann die Verwendung von PHP-"if"-Anweisungen für die Ergebnisse einer SELECT-Abfrage zur Bestimmung, ob eine INSERT-Abfrage ausgeführt werden soll, zu unbeabsichtigten Datenüberschneidungen

Ich bin Student und schreibe zum ersten Mal eine Software. Es ist eine Webanwendung auf einem LAMP-Stack, und als Teil dieser Webanwendung habe ich die folgende Funktion geschrieben, um mit der Datenbank zu interagieren, wenn ein neuer Benutzer erstellt wird:

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 wird an anderer Stelle als PHP-Datenobjekt initiiert.

Es folgt diesen grundlegenden Schritten:

  1. Abfrage der Datenbank, ob jemand bereits ein Konto mit dem gewünschten Benutzernamen verifiziert hat.
  2. Wenn der Benutzername verfügbar ist, führen Sie eine weitere Abfrage und die gleiche Prüfung für E-Mail durch.
  3. Wenn sowohl der Benutzername als auch die E-Mail verfügbar sind, werden Verifizierungscode, Salt und Hash des Passworts generiert, eine dritte Abfrage durchgeführt, um alles in die Datenbank zu schreiben, und 1 zurückgegeben (was Erfolg bedeutet).

Die Idee ist, dass Benutzernamen und E-Mails erst dann reserviert werden, wenn Ihr Konto verifiziert ist (verifiziert = "1"). An anderer Stelle gibt es ein Skript, das die Spalte "Verifiziert" auf "1" ändert, wenn Sie auf einen per E-Mail zugesandten Verifizierungslink klicken.

Meine erste Frage lautet wie folgt:

Person A schlägt den Benutzernamen "Lorem" vor, und Person B hat ein unverifiziertes Konto, das ebenfalls den Benutzernamen "Lorem" vorschlägt. Ist es möglich, dass die Abfragen in der folgenden Reihenfolge ausgeführt werden?

  1. Das Skript von Person A stellt fest, dass der Benutzername "Lorem" nicht von einem verifizierten Benutzer verwendet wird
  2. Das Skript von Person B verifiziert ihr Konto mit dem Benutzernamen "Lorem".
  3. Das Skript von Person A erstellt ihr unverifiziertes Konto mit dem Benutzernamen "Lorem".

Meine zweite Frage ist:

Ist es möglich, die 3 Abfragen in diesem Skript in 1 Abfrage mit der gleichen if/else-Logik in SQL anstelle von PHP ausgedrückt zu kombinieren, und wenn ja, würde das die Leistung verbessern und/oder verhindern, dass das oben genannte Szenario auftreten?

2voto

Andomar Punkte 224164

Für eine gleichzeitige Lösung könnten Sie die insert konditioniert:

insert  into users 
        (username, email, ...)
select  :username, :email, ...
where   not exists
        (
        select  *
        from    users
        where   verified > 0
                and (username = :username
                     or email = :email)
        )

Das ist in MySQL noch nicht 100% sicher, sollte aber in der Praxis ausreichen.

Beachten Sie, dass das Problem der Gleichzeitigkeit bei der Benutzererstellung ein Luxusproblem ist. Ich würde einfach eine Basisversion wie die, die Sie haben, einrichten und mich auf die interessanteren Aspekte Ihrer Website konzentrieren!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X