Problems with a signup errormessage

Hi there, I was creating error messages for my signup page if a username already exist, the email already exists etc. However, I always get a success message even if the new user has the same email address as another user = several users with the same email. I have looked inside my code, but I can’t find the problem, please help.

  • Thank you
**sql table:**
CREATE TABLE users(
    id INTEGER AUTO_INCREMENT PRIMARY KEY NOT NULL,
    uidUsers VARCHAR(32) NOT NULL,
    emailUsers VARCHAR(255) NOT NULL,
    pwdUsers VARCHAR(255) NOT NULL,
    nameUsers VARCHAR(255) NOT NULL
);

signup.php:

    <link rel="stylesheet" type="text/css"  href="login.css">
    <link rel="icon"       type="image/png" href="favicon.png">


<main>
    <?php
    //bruker get fordi vi henter informasjon fra url
        if (isset($_GET['error'])) {
            if ($_GET['error'] == "emptyfields") {
                echo '<p class="signuperror"> Fill in all fields!</p>';
            }
            else if ($_GET['error'] == "invaliduidmail") {
                echo '<p class="signuperror"> Invalid username and e-mail!</p>';
            }
            else if ($_GET['error'] == "invaliduid") {
                echo '<p class="signuperror"> Invalid username!</p>';
            }
            else if ($_GET['error'] == "invalidmail") {
                echo '<p class="signuperror"> Invalid e-mail!</p>';
            }
            else if ($_GET['error'] == "passwordcheck") {
                echo '<p class="signuperror"> Your passwords do not match!</p>';
            }
            else if ($_GET['error'] == "usertaken") {
                echo '<p class="signuperror"> Username is already taken!</p>';
            }
        }
        else if ($_GET['signup'] == "success") {
            echo '<p class="signupsuccess"> Signup successful!</p>';
        }
    ?>
</main>

<body>      
<div class="login-box">
    <h1> Sign up </h1>

    <div class="textbox">
    <form action="includes/signup.inc.php" method="post">
        <input type="text" name="uid" placeholder="Username">
    </div>

    <div class="textbox">
        <input type="text" name="mail" placeholder="E-mail">
    </div>

    <div class="textbox">
        <input type="password" name="pwd" placeholder="Password">
    </div>

    <div class="textbox">
            <input type="password" name="pwd-repeat" placeholder="Repeat password">
    </div>

    <button type="submit" name="signup-submit"> Signup </button>
    </form>
</div>
</body>

**signup.inc.php:**
<?php
if (isset($_POST['signup-submit'])) {
    
require "dbhandler.inc.php";

$username =         $_POST['uid'];
$email =            $_POST['mail'];
$password =         $_POST['pwd'];
$passwordRepeat =   $_POST['pwd-repeat'];

//Check if ANY columns is left empty while signing in, and keeping information that is already typed in before entering "sign up"
if (empty($username) || empty($email) || empty($password) || empty($passwordRepeat)) {
    header("Location: ../signup.php?error=emptyfields&uid=".$username."&mail=".$email);
    exit();
}
else if (!filter_var($email, FILTER_VALIDATE_EMAIL) && !preg_match("/^[a-zA-Z0-9]*$/", $username)) {
    header("Location: ../signup.php?error=invalidmailuid");
    exit();
}

else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    header("Location: ../signup.php?error=invalidmail&uid=".$username);
    exit();
} 
else if (!preg_match("/^[a-zA-Z0-9]*$/", $username)) {
    header("Location: ../signup.php?error=invaliduid&mail=".$email);
    exit();
}
else if ($password !== $passwordRepeat) {
    header("Location: ../signup.php?error=passwordcheckuid=".$username. "&mail=".$email);
    exit();
}
else {

    $sql = "SELECT uidUsers FROM users WHERE uidUsers=?";
    $statement = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($statement, $sql)) {
        header("Location: ../signup.php?error=sqlerror");
        exit();
    }
    else {
        mysqli_stmt_bind_param($statement, "s", $username);
        mysqli_stmt_execute($statement);
        mysqli_stmt_store_result($statement);
        $resultCheck = mysqli_stmt_num_rows($statement);
        if ($resultCheck > 0) {
            header("Location: ../signup.php?error=usertaken&mail=".$email);
            exit();
            }

        else {

            $sql = "INSERT INTO users (uidUsers, emailUsers, pwdUsers) VALUES (?, ?, ?)";
            $statement = mysqli_stmt_init($conn);
            if (!mysqli_stmt_prepare($statement, $sql)) {
                header("Location: ../signup.php?error=sqlerror");
                exit();
            }
            else { //bcrypt = latest version of hashing
                $hashedpwd = password_hash($password, PASSWORD_DEFAULT);

                mysqli_stmt_bind_param($statement, "sss", $username, $email, $hashedpwd);
                mysqli_stmt_execute($statement);
                header("Location: ../login.php?signup=success");
                exit();
            }
        }

    }

}
//Close connection
mysqli_stmt_close($statement);
mysqli_close($conn);
}

else {
    header("Location: ../signup.php");
    exit();
}

Relevant files:point_up_2:

Sorry for signup.inc.php, I don’t know how to get space between each else if statement, I can email the file to you if you want…

CREATE TABLE users(
    id INTEGER AUTO_INCREMENT PRIMARY KEY NOT NULL,
    uidUsers VARCHAR(32) NOT NULL,
    emailUsers VARCHAR(255) NOT NULL UNIQUE,
    pwdUsers VARCHAR(255) NOT NULL,
    nameUsers VARCHAR(255) NOT NULL UNIQUE
) engine=InnoDB;

Now you just do an insert and if it fails because of an error code 1062, a duplicate entry was attempted.

Thank you so much!
The table does not allow any user with the same email and username as another user now, but I still need an error message for this, do you have a quick error message similar to the others I have in my code that prevents the website from continuing to other files? Because now I end up proceeding just like if I had created a user, but the table wont add it in, so I basically ends up creating nothing…

  • Thanks anyways :slight_smile:

You would perform this test inside the error handling for the INSERT query’s execute() call. You are probably thinking, I don’t have any error handling for this.

You ALWAYS need error handling for every statement that can fail, so that your code will take a known execution path, both when statements work and when they don’t.

The easiest way of adding error handling for all the database statements that can fail - connection, query, prepare, and execute, is to use exceptions for errors and in most cases let php catch and handle the exception where it will use its error related settings to control what happens with the actual error information (database errors will ‘automatically’ get displayed or logged the same as php errors.) The exception to this rule is when inserting/updating duplicate or out of range user submitted data. In this case, which is what you are trying to do now, your code would catch the exception, test if the error number is for something your code is designed to handle, then setup message(s) telling the user exactly what was wrong with the data they submitted.

If you only have one database column defined as a unique index, a duplicate index error would mean that the value for that column already exists. However, since you have more than one column defined as being unique, it is at this point in the code that you would need to execute a SELECT query to find which columns contain duplicate values.

Some implementation suggestions that will reduce the amount of existing code by at least four times -

  1. By using exceptions for database statement errors, you will be able to remove the error handling logic you have now. You are not actually doing anything with the result of that logic and you should NOT tell a visitor to your site if or what type of error has occurred on the server.
  2. Put the form and the form processing code on the same page. This will allow you to validate all the inputs at once, without writing out logic for every combination of inputs and it will allow you to easily re-populate the form field values upon an error so that the visitor doesn’t need to keep re-entering the same values over and over.
  3. In case it was not clear, the unique index change to the database table means that you remove the initial SELECT query(ies).
  4. If you switch to the much simpler PDO database extension, over half of the database specific lines of code will go away.

Thank you for the detailed response :slight_smile:
This helped me a lot, and changed my perspective of understanding how this system works.

Sponsor our Newsletter | Privacy Policy | Terms of Service