Test for duplicates in a Mysql database? - php

so I have a simple newsletter signup form. I can add users into the database, but I want to account for duplicate emails. This is what I have right now.
$result = mysql_query("SELECT * FROM Users WHERE Email='$email'");
$num_rows = mysql_num_rows($result);
if($num_rows){
echo "You've already registered! Thanks anyway";
}
else{
mysqli_query($db_connection, "INSERT INTO Users (Name, Email) VALUES('$name' , '$email')");
echo "Thanks for signing up, $name.";
}
When I click submit, it will add it to the database, regardless if the email is the same.
The mysql_query that gets $result is fine. However, for some reason the if statement doesn't get called. Any idea why?

"The mysql_query that gets $result is fine"
Your DB connection sounds to be mysql_ - and you're using mysqli_ functions below that.
Use mysqli_ exclusively and do not mix them, they don't.
Sidenote: Your question is confusing.
You state: When I click submit, it will add it to the database, regardless if the email is the same. - then you say The mysql_query that gets $result is fine.
This: if($num_rows) should be if($num_rows >0)
Use this for your DB connection:
$db_connection = mysqli_connect("your_host","user","password","your_db");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
then do:
$result = mysqli_query($db_connection, "SELECT * FROM Users WHERE Email='$email'");
$num_rows = mysqli_num_rows($result);
if($num_rows >0){
echo "You've already registered! Thanks anyway";
exit;
}
else{
mysqli_query($db_connection, "INSERT INTO Users (Name, Email) VALUES('$name' , '$email')");
echo "Thanks for signing up, $name.";
}
Use http://php.net/manual/en/mysqli.error.php on your query.
I.e.: or die(mysqli_error($db_connection))
Warning
Your present code is open to SQL injection.
Use prepared statements, or PDO with prepared statements.
Footnotes:
If you want to avoid duplicates, set your column(s) as UNIQUE.

Related

Check and Return Value in Mysqli_query

I am Android developer and trying to make one API for register user using PHP and Mysqli. I have made API like below
<?php
include("dbconnection.php");
$email= $_GET['email'];
$query = mysqli_query($conn, "SELECT * FROM tbl_user WHERE email='".$email."'");
if (!$query){
die('Error: ' . mysqli_error($con));
}
if(mysqli_num_rows($query) > 0){
$response='success';
}else{
$sql = "INSERT INTO tbl_user(email)VALUES ('".$email."')";
if (mysqli_query($conn, $sql)) {
$response='success';
}else {
$response='error';
}
}
echo json_encode($response);
?>
basically I am passing email as parameter like example.com/login?=abc#gmail.com
and I want check that email is already in database table or not. if email exist in database I want return user_id in response and if email is not in database than I want add that email in database and want return user_id. I have made API is working fine as I require but I do not know how to return user_id located with that email. Let me know if someone can give me idea to solve my puzzle. Thanks
The below code will create an array with message and user_id.
include("dbconnection.php");
$email= $_GET['email'];
$query = mysqli_query($conn, "SELECT * FROM tbl_user WHERE email='".$email."'");
if (!$query){
die('Error: ' . mysqli_error($con));
}
if(mysqli_num_rows($query) > 0){
// assign message to response array
$response['message']='success';
// Get the results data
while($row = mysqli_fetch_assoc($query)) {
// assign user_id to response array
$response['user_id'] = $row['user_id'];
}
}else{
$sql = "INSERT INTO tbl_user(email) VALUES ('".$email."')";
if (mysqli_query($conn, $sql)) {
$response['message']='success';
// assign last inserted id to response array
$response['user_id'] = mysqli_insert_id($conn);
}else {
$response['message']='error';
}
}
echo json_encode($response);
Prepared statements help you secure your SQL statements from SQL Injection attacks.
First of all, you should use PreparedStatement to avoid sql injection.
Then, second you can use PDO::lastInsertId()

insert into multiple tables with register form

i have a register form and I tried to insert information into multiple tables but that second query doesn't work , i know i have to use user_id for second one but can someone explain to me how?
$sql="INSERT INTO users(firstname,lastname,email,password) VALUES('$firstname','$lastname','$email','$password')";
$sql2="INSERT INTO address(phone,city,address) VALUES('$phone','$city','$address')";
$result=mysql_query($sql);
if($result){
echo "Account Successfully Created";
} else {
echo "Failure!";
}
A quick/dodgy solution would be:
$sql="INSERT INTO users(firstname,lastname,email,password) VALUES('$firstname','$lastname','$email','$password')";
$result = mysql_query($sql);
if($result){
$userid = mysql_insert_id();
$sql2="INSERT INTO address(userid, phone,city,address) VALUES($userid, '$phone','$city','$address')";
$result = mysql_query($sql2);
}
You should use the newer mysql functions though - mysqli
http://php.net/manual/en/book.mysqli.php as mysql is deprecated.
If you decide to stick with mysql though - at the very least mysql_real_escape those values :)

SQL to PDO For Transferring Table Contents To Another Table

I am trying to change a email confirmation function written in sql to PDO. This is the tutorial for your further reference: http://www.phpeasystep.com/phptu/24.html.
This particular section will move the user's information from the temporary table to the permanent table after they click on the verification link sent to their email.
The problem I am having is under this header within that tutorial: STEP4: confirmation.php
My code is similar to that, but I added a few prepared statements as I am trying to prevent SQL injection.
To be clear: I am looking for direction on what else I need to do to switch this from sql to PDO and prevent any sql injection. Examples when providing an answer are crucial as I am a visual learner. Thank you.
Here is my code:
<?php
include('config.php');
//Test DB connection
try {
$conn = new PDO("mysql:host=$Host;db=$svrDb", Username, $Password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo 'ERROR: ', $e->getMessage(), "\n";
}
// Passkey that got from link
$passkey=$_GET['passkey'];
$sql1= $conn->prepare("SELECT * FROM temp_members_db WHERE confirm_code ='$passkey'");
$sql_conf1->execute() or die ('Error updating database: '.mysql_error());
$result1=$sql1->fetchall();
// If successfully queried
if($result1){
// Count how many row has this passkey
$count=mysql_num_rows($result1);
// if found this passkey in our database, retrieve data from table "temp_members_db"
if($count==1){
$name=$rows['name'];
$email=$rows['email'];
$password=$rows['password'];
$country=$rows['country'];
// Insert data that retrieves from "temp_members_db" into table "registered_members"
$sql2="INSERT INTO registered_members(name, email, password, country)VALUES('$name', '$email', '$password', '$country')";
$result2=mysql_query($sql2);
}
// if not found passkey, display message "Wrong Confirmation code"
else {
echo "Wrong Confirmation code";
}
// if successfully moved data from table"temp_members_db" to table "registered_members" displays message "Your account has been activated" and don't forget to delete confirmation code from table "temp_members_db"
if($result2){
echo "Your account has been activated";
// Delete information of this user from table "temp_members_db" that has this passkey
$sql3="DELETE FROM temp_members_db WHERE confirm_code = '$passkey'";
$result3=mysql_query($sql3);
}
}
?>
Ok, so you're on the right track but not quite....
The whole reason you use Prepared Statements is so that the database knows what to interpret as SQL, and what not to interpret as SQL. Right now, you have the following:
$sql1= $conn->prepare("SELECT * FROM temp_members_db WHERE confirm_code ='$passkey'");
$sql_conf1->execute() or die ('Error updating database: '.mysql_error());
$result1=$sql1->fetchall();
To take full advantage of PDO and Prepared Statements you should change it to something like this:
$sql1= $conn->prepare("SELECT * FROM temp_members_db WHERE confirm_code = ?");
try{
$sql1->execute(array($passkey));
}catch(PDOException $e){
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
$result1=$sql1->fetchall();
There are a couple reasons for this. In your code, you send the variable $passkey along with your prepare statement, so in essence the prepare operation is useless because $passkey has not been sanitized. Notice in my code I replaced it with a ?. This tells the database:
"Hey, I'm going to be executing a SELECT statement and I'm going to replace the ? with a value from one of my variables, so don't interpret that as SQL!"
Here is a great resource for PDO:
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

Prevent duplicate data being entered into mysql database

I'm trying to make my email subscription service reject emails that already exist within my database so users don't subscribe the same email twice. this is what I have but its not working, any ideas?
<?php
if(!isset($_POST['submit']))
exit();
$vars = array('email');
$verified = TRUE;
foreach($vars as $v) {
if(!isset($_POST[$v]) || empty($_POST[$v])) {
$verified = FALSE;
}
}
if(!$verified) {
echo "<p style='color:white; margin-top:25px;'>*Email required*</p>";
exit();
}
$email = $_POST['email'];
if($_POST['submit']) echo "<p style='color:white; margin-top:25px;'>*Check your inbox* </p>";
// Create connection
$con=mysqli_connect("mysql.host","user","password","dbname");
// Check connection
if (mysqli_connect_errno($con))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$sql="INSERT INTO emails (email) VALUES ('$_POST[email]')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
$query = mysql_query("SELECT * FROM emails WHERE email='$email'",($con));
if(mysql_num_rows($query) != 1)
{
echo "email already exists";
// redirect back to form and populate with
// data that has already been entered by the user
}
mysqli_close($con);
?>
The easiest way to let MySQL reject the duplicate e-mail address is to make the field unique (http://www.w3schools.com/sql/sql_unique.asp)
ALTER TABLE emails ADD UNIQUE (email)
However, MySQL will not return a warning
Use mysqli_num_rows($query) instead of mysql_num_rows($query)
$query = mysqli_query($con, "SELECT * FROM emails WHERE email='".$email."'");
if(mysqli_num_rows($query) > 0){
echo "email already exists";
}else{
$sql="INSERT INTO emails (email) VALUES ('".$_POST[email]."')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
}
Firstly, you're mixing MySQLi_ with MySQL_ so stick with MySQLi_ and modify the rest of your code accordingly.
This is the logic I use in my scripts, using ? instead of '$email'
$query = $con->query("SELECT * FROM emails WHERE email=?");
// $query = $con->query("SELECT email FROM emails WHERE email=?");
// you may need to use that one --^ if checking a particular column
$numrows=mysqli_num_rows($query);
if($numrows > 0){
die("Email already exists in the database, please try again.");
}
You can use this method, binding parameters. Assuming your column is named email
$query = "SELECT email FROM emails WHERE email=?";
if ($stmt = $con->prepare($query)){
$stmt->bind_param("s", $email);
if($stmt->execute()){
$stmt->store_result();
$email_check= "";
$stmt->bind_result($email_check);
$stmt->fetch();
if ($stmt->num_rows == 1){
echo "That Email already exists.";
exit;
}
}
}
Beside mixing mysql and mysli
Use > not !=
if(mysqli_num_rows($query) > 1)
But this approach means you already have duplicates.
Maybe this will help after you put an unique index on the email column.
As noted in the other answers, you mixed mysqli and mysql functions.
for exemple in both these lines you use mysql instead of mysqli functions.
$query = mysql_query("SELECT * FROM emails WHERE email='$email'",($con));
if(mysql_num_rows($query) != 1)
I also think your code is easily SQL Injectable.
You are using $_POST["email"] in your insert query, without sanitizing it.
Have a look to at least the sql injection wikipedia page
My answer would be as follows,
First, create a UNIQUE KEY of the email column, and then:
INSERT INTO `table` VALUES (/*etc*/) ON DUPLICATE KEY UPDATE /*set a column equal to itself*/
This allows you to attempt inserting into the database, and you can choose whether or not the query throws an error. If you want it to throw an error, then simply do not use ON DUPLICATE KEY, and then catch the SQLException that is thrown from the query and tell the user that the email already exists.
Add a unique constraint to the email column.
Test for error returned on insert or update. I believe the code may be influenced if it is a primary key, foreign key, unique constraint on an index.
With PHP you can use
if( mysql_errno() == X) {
// Duplicate VALUE
} else {
// fail
}
You can test it yourself with a duplicate email or here are the mysql_errNo return values
For non PHP, to determine correct error code test it yourself with a duplicate email or look at the following.
MySQL Errors

Checking if row exists under criteria (PDO, prepare???)

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.

Categories