I am making a website with a login system. When the user wants to sign up and enters his email, there should not exist one in the MySQL database already. I am trying to make my code through prepared statements.
When the user enters an email that already exists in the database I want it to send the user back to the same signup page with the header function with some kind of error. I tried to store the number of rows in a variable called $resultcheck and check whether or not there are columns that have the same email more than 0 (if it already exists).
Here is the code:
$query = "SELECT * FROM users WHERE Mail=?;";
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $query))
{
header("Location: ../registrering.php?error=sqlerror");
exit();
}
else
{
mysqli_stmt_bind_param($stmt, "s", $mail);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$resultCheck = mysqli_stmt_num_rows($stmt);
if($resultcheck > 0)
{
header("Location: ../registrering.php?error=emailtaken");
exit();
}
else {...}
When I submitted however an account with an already existing email in the database then I succesfully entered another column in the table users and have more than one column with the same email.
You are assigning $resultCheck and then testing for another variable called $resultcheck which will always be 0.
So your mistake is a typo in your variable naming.
Beside of checking with a SELECT SQL. You should set the column in mysql to unique. See https://www.w3schools.com/sql/sql_unique.asp.
Related
This question already has answers here:
How to search multiple columns in MySQL?
(6 answers)
Closed 2 years ago.
I have found out how to fetch for a username, however how would I do this with an email? Because, I want to add two separate error messages for an email and a username
$sql = "SELECT uid_users FROM users WHERE uid_users=?";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../register.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$resultCheck = mysqli_stmt_num_rows($stmt);
if ($resultCheck > 0) {
header("Location: ../register.php?error=usertaken&mail=".$email);
exit();
}
Use OR to check another column.
$sql = "SELECT uid_users FROM users WHERE uid_users=? OR email = ?";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../register.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "ss", $username, $email);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$resultCheck = mysqli_stmt_num_rows($stmt);
if ($resultCheck > 0) {
header("Location: ../register.php?error=usertaken&mail=".$email);
exit();
}
}
Note that this won't tell them whether it was the username or email that was already taken. If you want that, you should just do two separate queries, one that looks for a duplicate username, another that looks for a duplicate email.
Or you could change the query to SELECT uid_users, email and fetch the results of the query. Then check whether the fetched username or email matches the input, and display an appropriate error.
You can use the OR operator for this:
SELECT uid_users
FROM users
WHERE uid_users=?
OR email=?";```
If you want to check if a record exists in the database that matches both username and email then you should use WHERE uid_users=? AND email=?.
If you want to check if a a record exists in the database that matches either username or email, then use WHERE uid_users=? OR email=?.
Small note, you don't need to fetch the data if you only want to check existence of the record in DB. Simply let MySQL tell you the number of matching record. Use COUNT() for this purpose.
$stmt = $conn->prepare("SELECT COUNT(1) FROM users WHERE uid_users=? OR email=?");
$stmt->bind_param('ss', $username, $email);
$stmt->execute();
// Fetch value of COUNT(1) from DB
$resultCheck = $stmt->get_result()->fetch_row()[0];
if ($resultCheck) {
header("Location: ../register.php?".http_build_query(['error' => 'usertaken', 'mail' => $email]));
exit();
}
I am building a website where a user will enter data in a form, which will then be looked up in the database for other users that match the same criteria.
Where I am stuck is that I am trying to set up a second database that will store the search criteria they used plus some of their details. To be able to keep track of the line of data they added to the database I have included an ID to the database that will be auto incremented and would like to set this as a cookie.
In the code below, the $resultCheck is following a SELECT query that idetifies matching results.
Where should I be using setcookie in this example?
if ($resultCheck > 0) {
$sql = "INSERT INTO results (email, link, contactInfo, price) VALUES ('".$_SESSION['userEmail']."', '$link', '$contactInfo','$askPrice');";
$stmt = mysqli_stmt_init($conn);
exit();
}
else{
mysqli_stmt_bind_param($stmt, "ssss", $email, $link, $contactInfo, $askPrice);
mysqli_stmt_execute($stmt);
}
$resultId = $row['resultId'];
setcookie("resulId", $resultId, 0, '/');
header("Location: ../results.php");
exit();
}
I have a very basic PHP login system which I'm altering right now for a product. The user is able to register with a username/password and the information is stored into a database. However, I have a separate table called "act_codes" which has a row called "act". I want to store activation codes in that table. For example, I would have "Code1" "Code2" and "Code3" in the act row. The user would login with their username and password, but they'd also need to enter their activation code which is generated via my ecommerce platform and emailed to them.
So far I have this for validating username/password which works fine:
if(empty($username_err) && empty($password_err) && empty($code_err)){
$sql = "SELECT username, password FROM users WHERE username = ?";
if($stmt = mysqli_prepare($link, $sql)){
mysqli_stmt_bind_param($stmt, "s", $param_username);
$param_username = $username;
if(mysqli_stmt_execute($stmt)){
mysqli_stmt_store_result($stmt);
if(mysqli_stmt_num_rows($stmt) == 1){
mysqli_stmt_bind_result($stmt, $username, $hashed_password);
if(mysqli_stmt_fetch($stmt)){
if(password_verify($password, $hashed_password)){
session_start();
$_SESSION['username'] = $username;
$_SESSION['code'] = $code;
header("location: welcome.php");
} else{
$password_err = 'The password you entered was not valid.';
}
}
} else{
$username_err = 'No account found with that username.';
}
}
}
mysqli_stmt_close($stmt);
}
I can't seem to figure out how to alter this code to also include the validation of the activation code from my second table. Could someone help me out by chance? Thank you very much!
Some points:
as a side point: put session_start() at the top of the script
And include a die statement immediately after your header("Location:...);
Are these two lines in the wrong order?
mysqli_stmt_bind_param($stmt, "s", $param_username);
$param_username = $username;
They should be set frst and then bound.
To answer your query
You seem to want a MySQL JOIN such as :
SELECT users.username, users.password act.var_code
FROM users
LEFT JOIN act ON users.userid = act.userid
WHERE username = ?
This is a rough result as I can't see your table structre, but feel free to read other Stack Overflow questions on a similar vain.
What type of MySQL join you use is entirely up to you. I have used LFET JOIN simply as an example.
As also referenced by d3t0x in their answer you will need to bind the additional data returned by MySQL, as well.
Why not use an inner join and this will mean you can keep using just the one query:
$sql1 ="SELECT users.username, users.password, codes.code FROM users INNER JOIN codes ON users.username = codes.username";
You will also need to bind the returned code to a variable so you can compare it with the code in the session.
Something like:
mysqli_stmt_bind_result($username, $hashed_password, $code);
This is presuming your table structure is:
users table = username, password
codes table = username, code
Here is some background information on what I'm trying to do here. I'm try to create a registration form for my website (successful so far until this point). Data can be entered into the DB. The only thing I'm trying to do now is prevent duplicate email/usernames from being entered into the db. Through much stackoverflow research, I have found and tested the following code:
$query = "SELECT COUNT(*) AS num_rows FROM users WHERE email = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("s", $email);
if ($stmt->execute()) {
return $stmt->num_rows;
}
What I then do is following:
if(user_exists($user_email) > 0) {
echo "Email already exists!";
}
But is passes by this if statement as if the email does exist in the database!
The email I'm trying to enter, for my tests is testemail#testemailweb.com which is already in the database! Would someone possibly point out where I have messed up in my code? Is there a silly mistake that I could have possibly done when trying to perform this?
The fix for your particular problem here is by not using COUNT(*) as mentioned by John and not depend on mysqli_stmt->num_rows by using a buffered result set:
$query = "SELECT * FROM users WHERE email = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("s", $email);
return $stmt->execute() && $stmt->store_result() && $stmt->num_rows > 0;
Addendum
The only thing I'm trying to do now is prevent duplicate email/usernames from being entered into the db
You will want to use table constraints to prevent this (not just from the app, but anything else that can access the database). This has the added benefit of guarding against race conditions.
ALTER TABLE users ADD UNIQUE(email);
This will raise an error if you attempt to insert a row with an email value that already exists. You can check for this error on the application side and do whatever you want with it.
Your query will always return 1 row. COUNT(*) will return a result set even if only to report no rows match your query. As a result user_exists() always returns 1.
Change your query to:
$query = "SELECT * FROM users WHERE email = ?";
Now if no rows match your query $stmt->num_rows will be 0 so user_exists() will return 0.
change:
if ($stmt->execute()) {
return $stmt->num_rows;
}
What I then do is following:
if(user_exists($user_email) > 0) {
echo "Email already exists!";
}
to
$j=0;
if ($stmt->execute()) {
$j= $stmt->num_rows;
} else {
echo "Email already exists!";
}
I've created an arbitrary login system for users on the app I'm developing, and I am using mysqli to switch from MySQL. However, I'm having teething issues, as it will log you in successfully regardless of what data you enter. Obviously this is wrong, and I think it's got something to do with my fetch statements. Here is the code:
$sid = /* arbitrary value */
$con = new mysqli($mysql_host,$mysql_user,$mysql_password,$mysql_database);
$stmt = $con->prepare("SELECT uid, pwd FROM schools WHERE uid=?");
$stmt->bind_param("i", $sid);
$stmt->execute();
$stmt->bind_result($schoolid, $password);
$stmt->fetch();
$stmt->close();
Anybody know what's going on here and able to describe it in plain English to a relative coding newbie?
EDIT: the rest of the code is like this for the checking system. The entered user ID is $sid and the entered and encrypted password is $cleanpwd.
if ($sid == $schoolid and $cleanpwd == $password) {
header('Location: loginsuccess.php');
}
else {
header('Location: login.php?error=1'); }
It seems that if this is a login form are you getting the data first and then processing if it is correct? Or are you trying to process if it is correct (a userid and password combo in the SQL)? Because from this you are just putting in a userid and getting back a userid and password without checking if any entered password matches the database password associated with that userid.
If you want to see if the password and username match in the SQL you should try this:
$stmt = $con->prepare("SELECT uid, pwd FROM schools WHERE uid=? AND pass=?");
$stmt->bind_param("is", $sid,$form_password);
$stmt->execute();
otherwise you need to check if the data matches up later on.
if($_POST['form_pass'] == $password){
//log the user in
}