Search code examples
phpmysqlmysqliregistration

Query mySQL to check if user already exists in two tables


I am following a tutorial on how to create a user registration system for a website. I've made it to this step but I need to check multiple values in two tables to see if they exist. The tutorial doesn't do this.

Here is my registration form:

<form action="/members/register/" name="registerForm">
    <div>
        <h2>Register</h2>
        <h6>welcome</h6>
        <div class="register">
            <input type="text" name="firstname" placeholder="First Name" required>
            <input type="text" name="lastname" placeholder="Last Name" required>
            <input type="text" name="email" placeholder="Email" required>
            <label for="dob">Date of Birth:
                <input type="date" name="dob" id="dob" placeholder="Date of Birth" required>
            </label>
            <input type="text" name="username" placeholder="Username" required>
            <input type="password" name="password" placeholder="Password" required>
            <input type="password" name="passwordconfirm" placeholder="Confirm Password" required>
            <p>By creating an account you agree to our <a href="/legal/terms-of-use/">Terms &amp; Privacy</a>.</p>
            <button type="submit" name="registerNow">Register</button>
        </div>
    </div>
</form>

The mySQL database tables I need to check against are:

users
  -id
  -username
  -password
  -userID (foreign key)

registered
  -id
  -nameFirst
  -nameLast
  -email
  -dob

I need to create a query that checks if ANY of the following already exist: 1) first AND last name together, 2) username, or 3) email.

Furthermore, once I understand how to perform a query like this, I am still a little confused as to what the ? is in the query. Also, this code example only checks if the username exists and outputs 'Username already exists. Please choose another.' I need to output different things based on which fields already exist in the table(s). Here is the code from the tutorial:

if ($stmt = $con->prepare('SELECT id, password FROM accounts WHERE username = ?')) {
// Bind parameters (s = string, i = int, b = blob, etc), hash the password using the PHP password_hash function.
$stmt->bind_param('s', $_POST['username']);
$stmt->execute();
$stmt->store_result();
// Store the result so we can check if the account exists in the database.
if ($stmt->num_rows > 0) {
    // Username already exists
    echo 'Username already exists. Please choose another.';
} else {
    // Insert new account
}
$stmt->close();
} else {
// Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
echo 'Could not prepare statement!';
}
$con->close();

Would it be like this?

SELECT id, password 
FROM users, registered 
WHERE users.username = ? OR (registered.nameFirst = ? AND registered.nameLast = ?) OR registered.email = ?

And again, I am learning how to do this using the tutorial so I don't want to change anything to the code in terms of how it operates. I understand that there are much better ways of doing this. I am using this as a starting point to learn and progress from.


Solution

  • Since all you want to do is check whether the registration values already exist, it is probably easiest to use EXISTS subqueries rather than JOINing both tables together. Something like this:

    SELECT
        EXISTS (SELECT * FROM users WHERE username = ?) AS found_username,
        EXISTS (SELECT * FROM registered WHERE nameFirst = ? AND nameLast = ?) AS found_name,
        EXISTS (SELECT * FROM registered WHERE email = ?) AS found_email
    

    In this query the ? represent placeholders for the username, first name, last name and email values. The purpose of using prepared statements with placeholders is to protect against SQL injection, for more information on that see this Q&A. Using them also has the benefit of removing the need to escape special character in inputs (for example, if you wanted to insert O'Hara into the nameLast field using a value enclosed in single quotes).

    So, for your code, you would do something like:

    if ($stmt = $con->prepare('SELECT
            EXISTS (SELECT * FROM users WHERE username = ?) AS found_username,
            EXISTS (SELECT * FROM registered WHERE nameFirst = ? AND nameLast = ?) AS found_name,
            EXISTS (SELECT * FROM registered WHERE email = ?) AS found_email')) {
        // Bind parameters (s = string, i = int, b = blob, etc)
        $stmt->bind_param('ssss', $_POST['username'], $_POST['firstname'], $_POST['lastname'], $_POST['email']);
        $stmt->execute();
        $stmt->bind_result($found_username, $found_name, $found_email);
        $stmt->fetch();
        // Store the result so we can check if the account exists in the database.
        if ($found_username) {
            // Username already exists
            echo 'Username already exists. Please choose another.';
        }
        elseif ($found_name) {
            // Name already exists
            echo 'Name already exists. Please choose another.';
        }
        elseif ($found_email) {
            // Email already exists
            echo 'Email already exists. Please choose another.';
        }
        else {
            // Insert new account
        }
        $stmt->close();
    } 
    else {
        // Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
        echo 'Could not prepare statement!';
    }
    $con->close();