Checking if username already exists in db prepared statement - php

I am trying to check if a posted username already exists in my database. I am not sure where I am going wrong. The other conditions below are working correctly. When I submit the form I always receive "Username taken" even when no such name exists in my db. Any help would be greatly appreciated. Thanks!
$username = $_POST['username'];
$stmt = $mysqli->prepare('SELECT COUNT(*) FROM users WHERE username = ?');
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if(isset($_POST["submit"]))
{
if(empty($_POST["username"]))
{
echo '<script>alert("Username field empty")</script>';
} else if(empty($_POST["password"])) {
echo '<script>alert("Password field empty")</script>';
} else if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo '<script>alert("Incorrect email format")</script>';
} else if($stmt->num_rows > 0) {
echo '<script>alert("Username taken")</script>';

selec count(*) ... always returns 1 record, with the count. So, when you check else if($stmt->num_rows > 0), then it always returns true. You should check the value returned by count, not the number of records.

Related

I recieve a white page when the second condition is true in php

I am trying to make a condition where the code checks if a phone number exists in DB and then the username.
$query1 = "SELECT `Phone` FROM `NewUser` WHERE Phone=?";
$query2 = "SELECT `Username` FROM `NewUser` WHERE Username=?";
// checks the Phone number existence
if($stmt = $LINK->prepare($query1)){
$stmt->bind_param("s", $Phone);
if($stmt->execute()){
$stmt->store_result();
$Phone_check= "";
$stmt->bind_result($Phone_check);
$stmt->fetch();
if ($stmt->num_rows == 1){
echo "That Phone already exists.";
die();
}
}
}
// checks the Username existence
elseif($stmt2 = $LINK->prepare($query2)){
$stmt2->bind_param("s", $User);
if($stmt2->execute()){
$stmt2->store_result();
$User_check= "";
$stmt2->bind_result($User_check);
$stmt2->fetch();
if ($stmt2->num_rows == 1){
echo "That Username already exists.";
die();
}
}
}
if the first condition is true I get That phone already exists but if the second condition occurs I get a white page.
When I swap the conditions then I get "That Username already exists."
As was pointed out in the comments if($stmt = $LINK->prepare($query1)) will return true regardless of whether the record exists or not. You need to remove all these if statements and simplify your code.
If you do not need to fetch the data into PHP to use it for something else, then there is absolutely no reason to fetch it. You can just check if the row exists with SQL. Since both columns belong to the same table you can do it in a single statement, too.
$stmt = $LINK->prepare("SELECT COUNT(*) FROM `NewUser` WHERE Phone=? OR Username=?");
$stmt->bind_param("ss", $Phone, $User);
$stmt->execute();
$stmt->bind_result($exists);
$stmt->fetch();
if ($exists) {
echo "The phone number or the username already exists.";
die();
}

Why is this code to check duplicate usernames not executing properly?

$conn properly connects to the database.
The users table of the database consists of the following fields id,name, email, username and password. One of the entries in the table contains benedict as the value for the username.
Code:
$userslist = $conn->prepare("SELECT * FROM users WHERE username=?");
$userslist->bind_param("s",$user);
$usersresult=$userslist->execute();
if($userslist->num_rows>0)
{
$userErr="Username already exists";
$errors++;
}
Problem:
When I enter a username(which is being stored in $user) with benedict as the value, the code does not detect duplicate id in spite of already having such a username. Further, $userslist->num_rows when printed shows 0.
On the contrary the following code correctly identifies, that a duplicate id already exists and prints the errror. (this proves there is no connection error or table errors)
$query="SELECT * FROM users WHERE username='".$user."'";
$qresult=mysqli_query($conn,$query);
if($qresult->num_rows>0)
{ $userErr="Username already exists";
$errors++;
}
I am aware that unique key and PDO is a better solution. But why it doesn't prints proper results while using prepared statements.
An affected rows result of: -1 indicates the query returned an error and therefore wasnt executed.
Check your query for errors in column/tables names etc.
Is your connection working?
Please try the following to debug:
$userslist = $conn->prepare("SELECT * FROM users WHERE username=?");
$userslist->bind_param("s",$user);
$usersresult=$userslist->execute();
print_r($conn->error);
Id suggest using PDO to start with, it is much safer for DB queries. http://php.net/manual/en/book.pdo.php . I would also suggest that you use a count for this and not a SELECT *. This is a wasteful check to see if a row exists, it will be more efficient by using a count.
You would do this using PDO like this.
$stmt = $db->prepare("SELECT count(1) FROM users WHERE username=?");
$stmt->execute(array($user));
$result = $stmt->fetch();
if($result)
{
if($result[0] == 1) echo "Username already taken";
else "username free";
}
else
{
echo "error";
}
You could do something like this.
if(mysqli_num_rows($userslist) > 0){
echo "username already exists"
}
check if row exists with mysql - similiar question
Have you tried:
$conn = new mysqli("localhost","user","password","db");
$sql = "SELECT * FROM users where username='".$_POST['username']."'";
$result = $conn->query($sql);
$count = $result->num_rows;
if($count > 0)
{
echo "Username ".$_POST['username']." already exists!";
}
So error is not affected row: check why the query failed:
`
<?php
$userslist = $conn->prepare("SELECT * FROM users WHERE username=?");
$userslist->bind_param("s",$user);
$usersresult=$userslist->execute();
if($userslist->num_rows>0)
{
$userErr="Username already exists";
$errors++;
}
elseif($userlist->affected_rows == -1) {
echo 'An error occurred: ' . $conn->error;
}
?>
`
but you do realise, in the few milliseconds between the check and an actual insert, there might be an other user inserting that exact same name?
Added: how to do it when username is unique indexed:
<?php
$userslist = $conn->prepare("INSERT INTO users (username, name, etc) VALUES (?,?, ?)");
$userslist->bind_param("sss",$user, $name, $etc);
$usersresult=$userslist->execute();
if($conn->errno == 1062) {
$userErr="Username already exists";
$errors++;
}
elseif($conn->errno) {
echo 'An error occurred: ' . $conn->error;
}
else {
if($userlist->affected_rows == 1) {
echo 'success';
}
else {
echo 'unknown why not inserted';
}
}
?>

Comparing if values exists in a MySQL table using PHP

Given the following code:
$checkuname = $connect->prepare('SELECT * FROM user WHERE username = ?');
$checkuname->bind_param("s", $uname);
$checkemail = $connect->prepare('SELECT * FROM user WHERE email = ?');
$checkemail->bind_param("s", $email);
$match = 0;
if ($checkuname->execute()) {
//if username matches//
$erroruname = "This username exists, please enter a new one";
$match = $match + 1;
}
if ($checkemail->execute()) {
//if email matches//
$erroremail = "This email has been used, please enter another one";
$match = $match + 1;
}
if ($match == 0) { //if no match, good to push data into database// }
No matter what happens, it always returns me saying that username exists (when it doesn't).
Is there any way to correct this?
Or if you think there would be an easier or clearer way to check if both username and email exists in a database, please do share too.
Just to mention too: Most tutorials I have found uses a single variable to check, but I need to check 2 variables
"#Fred-ii- I'll invite you to post an answer and I'll mark it as solved – Timothy Wong Glash"
As requested by the OP:
You can do this in one query.
$query = "SELECT `email`, `username` FROM `user` WHERE email=? AND username=?";
if ($stmt = $connect->prepare($query)){
$stmt->bind_param("ss", $email, $uname);
if($stmt->execute()){
$stmt->store_result();
$email_check= "";
// Number of binded results must match the number of columns in SELECT
$stmt->bind_result($email_check, $username_check);
$stmt->fetch();
// or num_rows >0
if ($stmt->num_rows == 1){
echo "That records already exists.";
exit;
}
}else{ echo "Error: " . mysqli_error($connect); }
}
Well, you are checking if the query executes, but you are not checking if the values returned are correct or not. What you need to do is verify how many rows are returned after executing the query, if a row is returned the user has been found. You can do that with num_rows.

Email is already in database, returns as if it isn't

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!";
}

PDO and checking if username or email is taken

I am converting to PDO and I'm having a problem converting at the section where it checks to see if the username and email is taken or not.
below is the code:
<?php
session_start();
$host = "localhost";
$username = "root";
$password = "123";
$dbname = "test";
$conn = new PDO("mysql:host=$host;dbname=$dbname",$username,$password);
?>
<?php
if(isset($_POST['register'])){
$username = $_POST['username'];
$password = $_POST['password'];
$email = $_POST['email'];
$usernamecheck = $conn->query("SELECT `id` FROM `user` WHERE username='$username'");
$emailcheck = $conn->query("SELECT `id` FROM `user` WHERE email='$email'");
if(mysql_num_rows($usernamecheck) > 0){
echo "That username is already taken";
}elseif(mysql_num_rows($emailcheck) > 0){
echo "That e-mail address is already in use";
}
?>
The errors I get are at the two following lines:
if(mysql_num_rows($usernamecheck) > 0){
}elseif(mysql_num_rows($emailcheck) > 0){
Thanks in Advance.
You're using mysql_num_rows() for a PDO query. You can't mix these APIs.
You're also interpolating $_POST variables directly into your SQL, which is a no-no for security. The benefit of using PDO is that you can easily use SQL query parameters instead, which is much easier and more secure.
Here's how I'd code this task:
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT COUNT(*) AS count FROM `user` WHERE username=?");
$stmt->execute(array($username));
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$username_count = $row["count"];
}
if ($username_count > 0) {
echo "That username is already taken";
}
$stmt = $conn->prepare("SELECT COUNT(*) AS count FROM `user` WHERE email=?");
$stmt->execute(array($email));
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$email_count = $row["count"];
}
if ($email_count > 0) {
echo "That email address is already in use";
}
Also keep in mind that even if you check first, you should assume that someday two people may be trying to create the same username simultaneously, and if the code for their respective requests executes in just the wrong sequence, they could both be told the username does not exist, go ahead and INSERT it. So you should define a UNIQUE KEY on the columns that must be unique. Only the first one to INSERT will succeed, the other will get an error. So you must check for errors.
First of all, the entire task is rather pointless. Making a username unique makes no sense. Given email is used to identify a user, the username - or, rather - display name could be anything and allow duplicates, just like it is done right here, on Stack Overflow.
But if you want the username to be unique, obviously it can be done in one query, without any num rows functionality which being essentially useless
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT username, email AS count FROM `user` WHERE username=? OR email=?";
$stmt = $conn->prepare($sql);
$stmt->execute([$username, $email]);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row['username'] === $username) {
$errors[] = "Username is taken";
}
if ($row['email'] === $email) {
$errors[] = "Email is taken";
}
}

Categories