I am trying to verify whether or not a username and email address exist in my database and have tried to do a if, elseif, else statement to no avail.
I want to first run a check to see if the username is fine - obviously if not, an echo statement will appear. If the username doesn't exist, run an elseif statement to see if the email address is unique - again if not, another echo statement will appear. For the final statement, if all other conditions return false, I want to run the below code so that the user's input is submitted to the database.
I initially tried to declare two variables with a statement to check if the username=$username and email_address=$email_address then check to see if the number of rows returned from a mysqli_query is more than 1 for the username. I entered an elseif statement with the same but for email address but then I had an else statement with the below code in {} brackets.
I have deleted the original code because too many errors were thrown up, and was probably too convoluted and messy when a more elegant way to do what I was exists.
Any help would be appreciated.
if(isset($_POST['submit']))
{
$sql = "INSERT INTO users (first_name, last_name, username, email_address, password, gender, city, country, verification_code, verified, sign_up_date) VALUES (
'$first_name',
'$last_name',
'$username',
'$email_address',
'$password',
'$gender',
'$city',
'$country',
'$verification_code',
'1',
'$sign_up_date')";
$result = mysqli_query($conn,$sql);
header("Location:confirmation.php");
}
What you want is an integrity check on the data. You should do this check inside the database. The simplest way is with unique constraints/indexes:
create unique index unq_users_username on users(username);
create unique index unq_users_email on users(email);
If you attempt to insert or update a row so it violates these constraints, then your data modification step will fail with an error.
You need to create an index for them.
Use The following command to create the index:
CREATE UNIQUE INDEX index_name ON table_name (column_name)
Check This Link for more info: https://www.w3schools.com/sql/sql_create_index.asp
You could write a function to check your database first for example:
$errors = []; // you can add errors to this array.
if (isset($_POST['submit']))
{
// first do your validation here against empty values and invalid email
$sql = "SELECT * from users where email='$email' and username='$username'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
$errors[] = "Username and email has been taken.";
}
if (!empty($errors))
{
// loop through your errors and echo them
} else {
// insert your values into the database
}
}
Related
I'm trying to check an email against my database, and if it doesn't already exist, add it to the database.
$query = "SELECT * FROM users";
$inputQuery = "INSERT INTO users (`email`,
`password`) VALUES ('$emailInput',
'$passInput')";
$emailInput = ($_POST['email']);
$passInput = ($_POST['password']);
if ($result = mysqli_query($link, $query)) {
while ($row = mysqli_fetch_array($result)) {
if ($row['email'] == $emailInput) {
echo "We already have that email!";
} else {
mysqli_query($link, $inputQuery);
echo "Hopefully that's been added to the database!";
}
}
};
It can detect an existing email, it's just the adding bit...
Currently this seems to add a new empty row for each existing row (doubling the size).
I'm trying to understand why it doesn't add the information, and how to escape the loop somehow.
Also for good measure, everyone seems to reuse $query, but this seems odd to me. Is it good practice to individually name queries as I have here?
Please let me know if there's anything else I should add.
I am not going to talk about the standards but straight, simple answer to your question.
Approach - 1:
INSERT INTO users (`email`,`password`) SELECT '$emailInput', '$passInput' from DUAL WHERE NOT EXISTS (select * from users where `email` = '$emailInput');
Approach - 2:
- Create a unique key on email column
- use INSERT IGNORE option.
user3783243 comments are worth noting
Try this :
$emailInput = mysqli_real_escape_string($link, $_POST['email']);
$passInput = mysqli_real_escape_string($link, $_POST['password']);
$qry3=mysqli_query($link,"select * from users where `email`='".$emailInput."'");
$num=mysqli_num_rows($qry3);
if($num==1) {
echo "Email-Id already exists";
} else {
$inputQuery = mysqli_query($link,"INSERT INTO users (`email`, `password`) VALUES ('".$emailInput."', '".$passInput."')");
if ($inputQuery) {
echo "Hopefully that's been added to the database!";
}
}
Your code seems to be a bit over-engineered because why not to pass you $_POST['email'] to select query where clause
"SELECT * FROM users where email = $emailInput" and then check if it is there already.
Also, keep in mind that this is an example only, and you should always check and sanitize user input.
From another hand you can do it with MySQL only using INSERT ... ON DUPLICATE KEY UPDATE Syntax. https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
That requires to add unique key for email column.
this the php part
<?php
include 'assets/db.php';
if(isset($_POST["register"])){
$sql = "INSERT INTO table (name, email, user_name, pass)
VALUES ('".mysqli_real_escape_string($conn, $_POST["name"])."',
'".mysqli_real_escape_string($conn, $_POST["email"])."',
'".mysqli_real_escape_string($conn, $_POST["user_name"])."',
'".mysqli_real_escape_string($conn, $_POST["pass"])."')";
if ($conn->query($sql) === TRUE) {
echo "<script type='text/javascript'>window.top.location='_sign_in.php?l=1';</script>";
} else {
echo "<script type= 'text/javascript'>alert('Error! Please refresh the page and try again.');</script>";
}
$conn->close();
i am trying to avoid re-registration of any user_name, if user_name is already registered, redirect back to some page example- register.php?q=user_exists.
To avoid duplicate user names, add a unique index to the table:
ALTER TABLE `table` ADD UNIQUE(`user_name`)
This will cause the insert to fail allowing you to detect the failure without needing an additional SELECT to check for a duplicate.
If you want to ensure the error is due to a duplicate value, check for mysql error 1062
Error: 1062 SQLSTATE: 23000 (ER_DUP_ENTRY)
You can check for this by using mysqli::errno and then redirect by simply sending the Location header, ie:
if (!$conn->query($sql))
{
if ($conn->errno == 1062)
{
header("Location: register.php?q=user_exists");
die();
}
die('Critical Failure');
}
Edit: Instead of just down voting, how about commenting on what is wrong with this answer?
I have a table called user_bio, this table has one row, which was inserted manually:
id: 1
age: 30
studying: Business
language: English
relationship_status: Single
username: conor
about_me: This is conor's bio.
I have a page called account_settings_bio.php, from where the logged in user ($username) can edit their details. At the moment, when I log in as conor, I can UPDATE my data, but say for example I log in as Alice, Alice has no row in the database, therefore, I would have to INSERT data for her, but it doesn't seem to insert a new row for her.
Here is my approach:
if ($update_bio){
/*************************/
// need to check if the username has data already in the db, if so, then we update the data, otherwise we insert data.
$get_bio = mysqli_query($connect, "SELECT * FROM user_bio WHERE username ='$username'");
$row_returned = mysqli_num_rows($get_bio);
if ($row_returned == 1){
$update_details_query = mysqli_query ($connect, "UPDATE user_bio SET studying ='$new_studying', language ='$new_lang',
relationship_status = '$new_rel', about_me = '$about_me' WHERE username ='$username'");
} if ($row_returned == 0) {
$insert_query = mysqli_query ($connect, "INSERT INTO user_bio VALUES ('', '$age', '$new_lang','$new_rel', '$username', '$about_me'");
}
echo " <div class='details_updated'>
<p> Details updated successfully! </p>
</div>";
}
The UPDATE query works fine, when logged in as conor, data does change in the db, its just the INSERT which is not working.
The order of the inserted columns is not the same as in the database and there are missing some (studying).
To be sure, you could rewrite your insert SQL to be more explicit:
INSERT INTO user_bio (id, age, studying, language, relationship_status, username, about_me) VALUES (NULL, '$age', '$new_studying', '$new_lang','$new_rel', '$username', '$about_me'"
Note: why not use if($row_returned==0){ /* INSERT */ } else { /* UPDATE */ } instead of a double if?
The code below indicates my attempts to try and find out whether a row exists with the criteria gave in the code. It defaults to the else statement, correctly, but doesn't work with the 'if' statement if the if statement appears to be true (there are no emails down as ashfjks#sdhja.com), and instead the code proceeds. The latter part of this code is mostly to expand on the situation. the row can only exist or not exist so I don't understand why it's not strictly doing one or the other. I am converting into PDO for site secuirty, thats why not all is in PDO, yet. I am sorry if this question is too localised?
$stmt = $pdo->prepare("SELECT * FROM table WHERE email = ?");
$stmt->execute(array("$email"));
$row3 = $stmt->fetch(PDO::FETCH_ASSOC);
while($row = $stmt->fetch()) {
if ( ! $row3) {
// Row3 doesn't exist -- this means no one in the database has this email, allow the person to join
$query = "INSERT INTO table (username, email, password, join_date) VALUES ('$username', '$email', SHA('$password1'), NOW())";
mysqli_query($dbc, $query);
$query = "SELECT * FROM table WHERE username = '$username'";
$data2 = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_array($data2)) {
$recipent = '' . $row['user_id'] . '';
$query = "INSERT INTO messages (recipent, MsgTit, MsgR, MsgA, sender, time, readb, reada, MsgCon) VALUES ('$recipent', '$MsgTit', '$MsgR', '$MsgA', '$sender', NOW(), '$readb', '$reada', '$MsgCon')";
mysqli_query($dbc, $query);
// Aftermath.
echo '<p>Your new account has been successfully created. You\'re now ready to log in. After this you should implement basic character-details on your users profile to begin the game.</p>';
mysqli_close($dbc);
exit();
} }
else {
// An account already exists for this email, so display an error message
echo '<p class="error">An account already exists for this e-mail.</p>';
$email = "";
}
}
Your if statement will never be executed. You need to check the number of rows returned. This is what you want:
Note: I originally used $stmt->rowCount(), but the OP said that didn't work for him. But I'm pretty sure the cause of that error was coming from somewhere else.
if (!($stmt = $pdo->prepare("SELECT * FROM table WHERE email = ?"))) {
//error
}
if (!$stmt->execute(array("$email"))) {
//error
}
//The $row3 var you had was useless. Deleted that.
$count = 0;
while ($row = $stmt->fetch()) {
$count++;
}
//The query returned 0 rows, so you know the email doesn't exist in the DB
if ($count== 0) {
$query = "INSERT INTO table (username, email, password, join_date) VALUES ('$username', '$email', SHA('$password1'), NOW())";
if (!mysqli_query($dbc, $query)) {
//error
}
$query = "SELECT * FROM table WHERE username = '$username'";
if (!($data2 = mysqli_query($dbc, $query))) {
//error
}
while ($row = mysqli_fetch_array($data2)) {
$recipent = '' . $row['user_id'] . '';
$query = "INSERT INTO messages (recipent, MsgTit, MsgR, MsgA, sender, time, readb, reada, MsgCon) VALUES ('$recipent', '$MsgTit', '$MsgR', '$MsgA', '$sender', NOW(), '$readb', '$reada', '$MsgCon')";
if (!mysqli_query($dbc, $query)) {
//error
}
// Aftermath.
echo '<p>Your new account has been successfully created. You\'re now ready to log in. After this you should implement basic character-details on your users profile to begin the game.</p>';
mysqli_close($dbc);
exit();
}
}
//The query did not return 0 rows, so it does exist in the DB
else {
// An account already exists for this email, so display an error message
echo '<p class="error">An account already exists for this e-mail.</p>';
$email = "";
}
And you should totally convert the rest of those queries to use PDO.
+1 to answer from #Geoff_Montee, but here are a few more tips:
Make sure you check for errors after every prepare() or execute(). Report the error (but don't expose your SQL to the user), and fail gracefully.
Note that even though you checked for existence of a row matching $email, such a row could be created in the brief moment of time since your check and before you INSERT. This is a race condition. Even if you SELECT for a row matching $email, you should also use a UNIQUE constraint in the database, and catch errors when you execute the INSERT in case the UNIQUE constraint blocks the insert due to conflict.
SELECT email instead of SELECT *. If you have an index on email, then the query runs more efficiently because it can just check the index for the given value, instead of having to read all the columns of the table when you don't need them. This optimization is called an index-only query.
Likewise use SELECT user_id instead of SELECT *. Use SELECT * only when you really need to fetch all the columns.
Bcrypt is more secure than SHA for hashing passwords.
I have set my database fields "username" and "email" to unquie, when using the code below this only works if the "username" already exists, an error is then echoed. If they email exists the user gets a mysql duplicate error, when the same error as above should be shown.
<?php
require_once ( 'connection.php' );
$username=$_POST['username'];
$password=md5($_POST['password']);
$email=($_POST['email']);
$ip=$_SERVER['REMOTE_ADDR'];
session_start();
$query = "INSERT INTO users (username, password, email, rank, ip, active) VALUES ('$username','$password', '$email', '1', '$ip', '0')";
$sql = "SELECT username AND email FROM users WHERE username = '$username' AND email = '$email'" ;
$result=mysql_query($sql);
$count=mysql_num_rows($result);
$row = mysql_fetch_array($result);
if ( $count== 0 )
{
if (!mysql_query($query))
{
die('Error: ' . mysql_error());
}
echo "You are signed up, please follow the link on your email to active your account.";
}
else
{
echo "Username or Email already exists"."<br>Try Again</br>";
}
?
Thanks
Try switching
WHERE username = '$username' AND email = '$email'"
to
WHERE username = '$username' OR email = '$email'"
Edit: I'm trying to guess what you're trying to do here. From your description, it seems you want either the username or the email to be unique and you have two separate unique indexes on those columns. Your code checks for the combination of username and email to be unique.
Edit 2: Also, I think you might want to look into the concepts of SQL Injection and Concurrency.
Switch to an OR clause in your WHERE statement instead of AND.
Also, DO NOT use the values given in $_POST (or $_GET and $_REQUEST for that matter) without making sure they are safe. What would happen if I sent a username with SQL in it?
','','','','',''); DELETE FROM users;
Make sure you using add_slashes() or a similar process to clean the data before sending to the database.