How do I check if a username exists using PDO? All I need to know is a bool true (exists) or false (does not). I have the initial parts set up but am unsure what to do next
$sthandler = $dbhandler->prepare('SELECT username FROM userdb WHERE username=? LIMIT 1');
$sthandler->execute(array('username'));
// ... What's next?
Check for the row count:
if ( $sthandler->rowCount() > 0 ) {
// do something here
}
Just grab the row:
if( $row = $sthandler->fetch() ){
// User exists: read its details here
}else{
// User does not exist
}
$username_exists = (bool) $sthandler->fetchColumn();
Note that you can even optimize the query a tiny bit since actually you don't need to select the username.
SELECT username FROM userdb ...
becomes
SELECT 1 FROM userdb ...
Related
I'll start this by saying that I am very new to SQLite (this is basically my first time properly trying it out), but I am familiar with SQL via MySQL and have used that plenty.
I have verified that my SQLite 3 database is working using a program called "DB Browser For SQLite". Right now it's empty, and I'm testing a user sign up system. I'm trying to do a check where I take the e-mail and username provided and check them against the database to confirm they haven't already been used by counting the returned rows. Seeing as my database is empty at the moment, I would expect a result of 0 regardless of what I submit, but I keep getting a result of 1.
$db = new SQLite3('database.db');
$email = SQLite3::escapeString($_POST['email']);
$username = SQLite3::escapeString($_POST['username']);
// check if email already exists
$email_query = $db->query("SELECT email FROM users WHERE email='$email' LIMIT 1;");
$email_exists = $email_query->numColumns();
// check if username already exists
$username_query = $db->query("SELECT username FROM users WHERE username='$username' LIMIT 1;");
$username_exists = $username_query->numColumns();
When I run those queries in "DB Browser For SQLite", I get the expected results. I'm not getting any PHP errors either. My one theory is that the 1 that is being returned by numColumns() is actually error code 1, but when I use SQLite3::lastErrorCode(), I get 0, meaning no errors. I'm lost...would really love some insight here!
The number of columns is just the number of fields you requested. If you had done SELECT username, email ... it would have returned 2 because you selected 2 columns.
If you want to know if there are any matches, you should count the number of rows, not columns. But the SQLite3 extension doesn't provide a numRows method. You could change your query so you do:
SELECT COUNT(*) AS count FROM users WHERE email = '$email'
and then see whether $row['count'] is greater than 0. Or you could use your existing query and try to fetch the result.
$email_exists = !empty($email_query->fetchArray());
When there are no rows, numColumns() will return 1. The solution, is to do this:
if ($username_query->numColumns() && $username_query->columnType(0) != SQLITE3_NULL) {
// Rows exist
} else {
// No data
}
Credit goes to Jon Scully.
Other comments suggest though that columnType may always return SQLITE3_NULL, and to instead do this to determine if there are rows:
if ($result->fetchArray()[0] == null) {
// No rows
}
$email_query = $db->query("SELECT email FROM users WHERE email='$email' LIMIT 1;");
if($email_query->fetchArray(SQLITE3_ASSOC)){
//email exists
}
If I have a query,
SELECT (...) FROM User WHERE Username = (...) AND Password = (...);
and the user types in an invalid Username is there a way to pick up that it was specifically the Username that was incorrect?
This is so that I can give more specific error messages to the user, like "User does not exist" etc...
SELECT COUNT(*) AS `count` FROM `User` WHERE `Username` = ...;
if( $result['count'] < 1 )
{
// no user
}
// repeat for pass.
I would select the username and then a bit-field on if the password matched. So remove the password part from the WHERE clause, and move it into the SELECT clause. Then, no matching rows means invalid username, and if you have a row, you need to check that field to see if the password matches.
SELECT (...) IF(password=?, 1, 0) as success
FROM User
WHERE Username = ?
If you're adamant about doing it this way, you can do:
SELECT password FROM user WHERE username = ?
If there's no record found, the username doesn't exist. If it does, you can now compare the password.
If your only goal is to check if a row exists in php (true or false), what is the best way to do it?
Option 1?
$result = mysql_query("SELECT * FROM users WHERE id = '1'");
$num_rows = mysql_num_rows($result);
if ($num_rows == 1)
// one user, like it should be.
else
// do something else
Option 2?
$query = mysql_query("select count(1) from users where id = 1")
if (mysql_result($query, 0) == 1)
// one user, like it should be.
else
// do something else
Option 3?
$query = mysql_query("something like SELECT EXISTS( SELECT */1/COUNT(*)/etc. ...)")
if (mysql_result($query, 0) == 1)
// one user, like it should be.
else
// do something else
Beter option 4?
you name it.
Subquestions
COUNT(*), COUNT(1) or COUNT(id)?
Option 3 is the fastest way to check if a row exists if you are using MySQL:
$query = mysql_query("SELECT EXISTS(SELECT 1 FROM users WHERE id = 1)")
if (mysql_result($query, 0) == 1)
// one user, like it should be.
else
// do something else
I think the question refers more the code itself then the time involved, so using his query:
$result = mysql_query("SELECT * FROM users WHERE id = '1'");
//if result not returned(false) from Mysql return False Else True
//This is just example and you can do anything you need in side the if()
if(!$result) {
//or return some error or redirect to another piece of code
return FALSE;
} else {
//or do some other php/mysql magic
//if there is a result you have the row to work with of needed
return TRUE;
}
mysql_query
...excerpt from PHP manual Return Values
For SELECT, SHOW, DESCRIBE, EXPLAIN and other statements returning
resultset, mysql_query() returns a resource on success, or FALSE on
error.
For other type of SQL statements, INSERT, UPDATE, DELETE, DROP, etc,
mysql_query() returns TRUE on success or FALSE on error.
The EXISTS is faster then SELECT COUNT(*) because the subquery will stop searching when it finds one row. It won't have to find them all and count them. It will return either 0 or 1:
SELECT EXISTS
( SELECT * FROM ... )
Why does this portion of code return true even when it shouldn't be?
$stmt = $dbh->prepare("SELECT COUNT(`user_id`) FROM `users` WHERE `username`= :username LIMIT 1");
$stmt->bindParam(':username', $username);
$stmt->execute();
return ($stmt->rowCount() == 1) ? true : false;
If I enter a username in a field that has already been registered, it returns true which then outputs:
That username has already been taken!
But if I enter a username that hasn't been registered, it still returns true and outputs the line above. I'm unsure why this is and how it can be fixed.
I know that the PHP manual states that rowCount() has some issues with SELECT queries, but I can't find a workaround for this that returns the number of rows affected by a SELECT query.
Because COUNT() will always return 1 row, although its value may be 0.
You can do a SELECT TRUE instead:
SELECT TRUE FROM `users` WHERE `username`= :username LIMIT 1
Or you can check if the value is greater than 0:
return ($stmt->fetchColumn() > 0);
BTW - the "? true : false" part is redundant; having the boolean condition by itself does just that.
You are checking the number of result rows. As your query returns always exactly one result row, rowCount() returns 1. The one result row will contain the count, e.g. 0 or 1 in with your query.
You need to check that count value in the result-row or change your query to not return any rows in case the user does not exists.
Try simple without binding:
$res = $dbh->query('SELECT COUNT(`user_id`) AS total FROM `users` WHERE `username`= "'.$username.'" ')->fetch();
return ($res['total'] == 1) ? true : false;
I am having trouble with a function that checks if a set of user entered info (username and password) exists within either of the two possible tables where this information is stored.
The first table is the users table. It contains the first set of specific user information.
The last table is the listings table. It contains the second set of specific user information.
I have basically modified my original code to include the new listings table, and hence the trouble coming from within that task. The old code basically counted the number of results in the users table, if the result was greater than 0, then the function returned true, else false.
Now I have been stuck on the best way to go about adding another table to the query, and function. So I have been playing around with a union.
This was the original query:
SELECT COUNT(*) FROM users
WHERE id='$accNum' AND password='$password'
This returned a count of either 0 or 1 based on the info stored in the users table.
This is how I have reworked the query to include a count of the additional listings table:
SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
This returned a result set of two rows, the first relating to the users table, and the second relating to the listings table. Then a column called COUNT (*) that contained the result count. This is the result set that I see within php myadmin.
Now this is the function:
function databaseContainsUser($accNum, $password)
{
include $_SERVER['DOCUMENT_ROOT'] . '/../../includes/db.inc.php';
$accNum = mysqli_real_escape_string($link, $accNum);
$password = mysqli_real_escape_string($link, $password);
$sql = "SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
";
$result = mysqli_query($link, $sql);
if (!$result)
{
$error = 'Error searching for user.';
include 'error.html.php';
exit();
}
$row = mysqli_fetch_array($result);
if ($row[0] > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
The problem that I have, is trying to work out how exactly to check the results to ascertain if the given log in credentials are valid.
I tried this: if (($row[0] > 0) || ($row[0] > 0)) But a var dump on $row showed that only the first row (count of users table) was being added to the array.
So I decided that this was complicated, and a long way to the final result.
So I tried selecting only the id column of the result as in:
...
`COUNT( * )` to `id`
...
$data = mysql_query($sql);
$num_sql = mysql_num_rows($data);
if ($num_sql > 0)
...
But this did not work out for me either.
But in either instance, my hours of trial and error have provided me with no success... So I've decided to seek help from the knowledgeable members of Stack Overflow!
So my question is this, what would be a logical way of going about this task? I am looking for any suggestions, or positive input what so ever here.
As I am fairly new to dabbling with PHP and mysql, if you would like to provide some code to explain your suggestions or input on the matter, it would more than likely help me to better understand the answer.
If you are checking existence only try doing this that way:
select case when
exists (SELECT 1 FROM users WHERE id = '$accNum' AND PASSWORD = '$password') or
exists (SELECT 1 FROM listings WHERE id = '$accNum' AND PASSWORD = '$password')
then 1 else 0
end as itDoesExist
It returns always one row with one column with 1 when record exists in at last one table (else 0).
Do not use count to check whether some specific record/-s exist/-s in table, it's usually slower than simple exists.
Looks like you're going to get two rows in the result no matter what. Try this:
$sql = "SELECT id,password
FROM users
WHERE id = '$accNum' AND password = '$password'
UNION
SELECT id,password
FROM listings
WHERE id = '$accNum' AND password = '$password'
";
Now you can just check mysql_num_rows() to see if there's a match in either of the tables.
There are a couple of ways to go about this; if we are to stick with the approach you started with; you can simplify the query to:
$sql = "SELECT COUNT(1) FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (SELECT COUNT(1) FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password')";
The reason you are only seeing one result, is because thats the way mysql_fetch_array() works, try doing this to get all results:
while ($row = mysql_fetch_array($result)) {
$data[] = $row;
}
var_dump($data);
Now you should have both values in there to validate with your conditional statements.