-2

I'm trying to check the database for a taken username when the user signs up. The connection to the database works fine as a similar password will be added to the table.

$username = $_POST['user'];
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT);

$s = 'SELECT * FROM users WHERE username = "$username"';

$result = mysqli_query($con, $s);

$num = mysqli_num_rows($result);

if ($num == 1) {
    echo "Username is taken";
}else {

table for users

It goes to the else and adds the username to the database anyways. I have checked to make sure there isn't more than one username, although a greater than sign would work better anyway. any ideas?

Dharman
  • 30,962
  • 25
  • 85
  • 135
user-313
  • 7
  • 4
  • Possibly there are 2 or more *same* usernames in your db? – GetSet Feb 09 '20 at 16:17
  • Sorry, I do have prepared statements for the other part and was planning on it once I could get this part to actually work. Thanks for reminding though. – user-313 Feb 09 '20 at 16:21
  • `if ($num == 1)` ... if there are already 2 or more *same* usernames in you db, this condition will always default to the `else`. So ensure that previous test cases didn't add duplicate usernames to your db. – GetSet Feb 09 '20 at 16:23
  • yeah at the moment the usernames I tried (and deleted afterward) only had one of themselves in the table. The result could only be 0 or 1. – user-313 Feb 09 '20 at 16:25
  • @Wenis then `echo` out `$num`. What's its value? – GetSet Feb 09 '20 at 16:30
  • I'm wondering why you're using `password_hash()`. – Funk Forty Niner Feb 09 '20 at 16:30

2 Answers2

2

Your code must be using parameter binding to send the value of $username to the database, otherwise "$username" is treated as a literal string. It will also protect your from SQL injections.

It would probably be better to create a UNIQUE key on that column instead. If you want to do it in the application layer for whatever reason, you can fetch the result and use that.

$stmt = $con->prepare('SELECT * FROM users WHERE username = ?');
$stmt->bind_param('s', $username);
$stmt->execute();
$result = $stmt->get_result()->fetch_all();

if ($result) {
    echo "Username is taken";
} else {
    // No such username in the database yet
}

This is not going to be very efficient, so we can simplify it using COUNT(1). It will return a single value containing the number of matching rows.

$stmt = $con->prepare('SELECT COUNT(1) FROM users WHERE username = ?');
$stmt->bind_param('s', $username);
$stmt->execute();
$usernameTaken = $stmt->get_result()->fetch_row()[0];

if ($usernameTaken) {
    echo "Username is taken";
} else {
    // No such username in the database yet
}

For more explanation see https://phpdelusions.net/mysqli/check_value

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • I posted a comment under their question on why they're using `password_hash()`. I think you might be chased down a rabbit hole here. – Funk Forty Niner Feb 09 '20 at 16:32
  • @FunkFortyNiner I think this is just part of the code which follows. In the else part they would create new account – Dharman Feb 09 '20 at 16:33
  • @FunkFortyNiner I just tested it out and it works. The two lines related to password are not relevant for the answer, so I will remove them. – Dharman Feb 09 '20 at 16:34
  • I don't question your answer :) I was just unsure as to their inclusion of `password_hash()`. – Funk Forty Niner Feb 09 '20 at 16:36
  • I wonder why my first comment asking if you were 100% sure was deleted. – Funk Forty Niner Feb 09 '20 at 16:56
  • @FunkFortyNiner I flagged it as not longer needed. :D I don't like comments loitering around. If they don't add anything I flag them. – Dharman Feb 09 '20 at 17:01
  • Thing is, when something is missing and there's more comments after, people will wonder why the other comments where the original context/question was lost. I don't know why you did that. – Funk Forty Niner Feb 09 '20 at 17:06
  • The other comments are still relevant even without our first two comments. I didn't flag others as they add value, but the first one and my reply became obsolete once I tested it out and you expanded on your point. Now by talking about our comments we of course added twice as much noise, so my comment cleanup efforts failed. – Dharman Feb 09 '20 at 17:08
-2

$s = 'SELECT * FROM users WHERE username = "$username"';

You are using double quote inside single quote so there is no interpolation happening. Change the order to

$s = "SELECT * FROM users WHERE username = '{$username}'";

Suman B
  • 86
  • 1
  • 6