Checking for duplicates in database table before inserting - php

I need to create a form that gathers a first name, last name, and an email address. I have created a table in MySQL called guestbook. The table looks something like the following:
CREATE TABLE guestbook (
id int unsigned NOT NULL AUTO_INCREMENT,
firstName varchar(50) NOT NULL,
lastName varchar(50) NOT NULL,
email varchar(250) NOT NULL,
status int NOT NULL,
sort int NOT NULL
);
And here is my code thus far:
<?php
Global $Conn;
$Conn = new mysqli("localhost","151_millet","2gZMXYGC","GUESTBOOK");
if(!$Conn) {
$ErrorMsg = "Couldn't connect to the database";
}
$FName = $_POST["fname"];
$LName = $_POST["lname"];
$Email = $_POST["email"];
// The series of ifs below tests to see if each field is blank
// If it is blank it will output an error message for each that is blank
if($FName == "") {
$ErrorMsg .= "First Name Was Left Blank<br>";
}
if($LName == "") {
$ErrorMsg .= "Last Name Field Was Left Blank.<br>";
}
if($Email == "") {
$ErrorMsg .="Email field was left blank.<br>";
}
I have no idea how to check for duplicates in the email field. Any help would be appreciated. I think I need to come up with a way to test $_POST against whats already in the db.

Alrighty, now we've cleaned up this question a bit. Let's get down to business.
You want to check for duplicates in your database. There are a couple of things you need to do for this. Let's try to keep this as simple as possible while we're working on it too.
First off, it's good to see you're using MySQLi and not the deprecated mysql_* functions. But we can handle MySQLi in a more object oriented manner. Also, using globals is frowned upon (and is actually not necessary, even in your current code!)
One other thing to note is that there are slightly different styles of code used in modern PHP, like camel case, and how you format if statements. If you're interested in learning PHP, then you should take a look at the PHP-FIG PSRs.
<?php
$conn = new mysqli("localhost", "151_millet", "2gZMXYGC", "GUESTBOOK");
if ($conn->connect_errno) {
// This is an error that will stop us from continuing, so assigning
// the error message to a string, doesn't really help us in this case
// The application NEEDS to stop
throw new RuntimeException("Unable to connect to MySQL database.");
}
$firstName = $_POST["fname"];
$lastName = $_POST["lname"];
$email = $_POST["email"];
if (!$firstName || !$lastName || !$email) {
echo "Please make sure to fill in all of your details.";
// You may want to handle this differently, this is just to keep things
// Very simple
exit;
}
$query = "SELECT COUNT(1) FROM guestbook WHERE email = ?";
$stmt = $conn->prepare($query);
$count = 0;
if ($stmt) {
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->store_result();
$count = $stmt->num_rows;
$stmt->close();
}
if ($count > 0) {
echo "A user with that email address already exists.";
exit;
}
// Do other stuff
That should help you out with what you need to do to check if an email address already exists. But you should also enforce this in your database by adding a unique key to the email column. That will mean that even if your code fails and would allow a duplicate email address entry, your database won't.

Related

Php don't send empty value

I've created a code that updates an Sql entry, but when you leave an value blank, it removes the existing value.
<?php
$servername = "localhost";
$username = "root";
$password = "HahahNo";
$dbname = "DATA";
$id = $_POST["id"];
$firstname = $_POST["firstname"];
$lastname = $_POST["lastname"];
$email = $_POST["email"];
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "UPDATE MyGuests SET firstname='$firstname', lastname='$lastname', email='$email' WHERE id=$id";
if ($conn->query($sql) === TRUE) {
echo "Success";
} else {
echo "Error updating record: " . $conn->error;
}
?>
Is there any way not to clear the not filled in values? Im fairly new to php.
Check if $_POST contains values.
First check if $_POST value has been set with isset() (has been posted).
Then check if the string isn't empty with strlen():
if (!isset($_POST['firstname'] || strlen($_POST['firstname']) == 0) {
echo 'Please enter first name';
} else {
// Do your DB update
}
Edit: Naturally empty() is better because you only need one check to do:
if (empty($_POST['firstname']) {
echo 'Please enter first name';
} ...
Thanks to #Fred -ii-
Edit II: As pointed out by #alex
if ($_POST['firstname']) {
echo 'Please enter first name';
} ...
would work too. Explained in PHP type comparison tables
You can write condition before execute function,
//all values are not null then update is perform
if(!is_null($firstname) && !is_null($lastname) && !is_null($email)){
if ($conn->query($sql) === TRUE) {
echo "Success";
} else {
echo "Error updating record: " . $conn->error;
}
}
What you're looking for is validation of user-supplied data. You're right - a user who hasn't read the instructions of your form could cause unintended data loss. Additionally a malicious user or innocent child could cause more harm with SQL injection.
First check your field meets minimum requirements. You could validate email addresses, postcodes, phone numbers, URLs... but to answer your question Daenu's answer is perfect.
Once you are satisfied the data meets your databases' requirements, check it is safe. Strip it of any malicious SQL commands. You can use prepared statements with PDO or MySQLi.
Also think about the specification of the data. Is the data type of each field a string or integer or float? What character set is your web page in (UTF-8 is a safe choice) and therefore what character set does your data arrive with? Does your database match (UTF8MB4 is a good companion)?

Can't get php to post to mysql

Hello I cannot get my php to post to mysql. I get no errors when submitting, but entries are not showing up in my database. I appreciate anyone that can give me advice on how I can fix this. I tried to search around here but couldnt find a dirrect reason on why my php code is not working.
<?php
if (isset($_POST['submit'])) {
if (empty($_POST['element_1']) || empty($_POST['element_2'])) {
die("You have forgotten to fill in one of the required fields! Please make sure you submit your name, and paypal e-mail address");
}
$entry = htmlspecialchars(strip_tags($_POST['entry']));
$timestamp = htmlspecialchars(strip_tags($_POST['timestamp']));
$name = htmlspecialchars(strip_tags($_POST['element_2']));
$email = htmlspecialchars(strip_tags($_POST['element_1']));
$comment = htmlspecialchars(strip_tags($_POST['element_3']));
$comment = nl2br($comment);
if (!get_magic_quotes_gpc()) {
$name = addslashes($name);
$url = addslashes($url);
$comment = addslashes($comment);
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
die("The e-mail address you submitted does not appear to be valid. Please go back and correct it.");
}
mysql_connect('host', 'username', 'password') ;
mysql_select_db('database name');
$result = mysql_query("INSERT INTO payments (entry, timestamp, name, email, comment) VALUES ('$entry','$timestamp','$name','$email','$comment')");
header("Location: post.php?id=" . $entry);
}
else {
die("Error: you cannot access this page directly.");
}
?>
Thanks in advanced for your time, understanding, and knowledge. I greatly appreciate it.
advice on how I can fix this
use var_dump($_POST); after if(isset($_POST['submit']))
do $sql="" and var_dump($sql) and mysql_query($sql);
after query var_dump(mysql_insert_id());
and var_dump(mysql_error());
and dont forget: error_reporting(E_ALL); at the top of the file
Then look what happens
[optional] after first query use SHOW COUNT(*) WARNINGS
Things you should check:
I cant see your database design, so you'll have to make sure that your database columns and table match correctly with what is specified in your database.
echo your variables to make sure none are empty.
Ensure that you are not inserting a string in column of type int or vice versa.
Make sure your form method is POST and that your name attributes match what you have specified in your variables ie $_POST['name_attr'].
The order of your insert columns should be the same order as in your table.
Lastly, i hope host,username,password and database name are just placeholders for your real database info? if not, that's the problem.

Trouble dealing with results from a SELECT query with MySQLI

The basic control structure I'm trying to get to work is to query the DB with the username and email, both of which are unique keys, and if either are in the DB let the user know that they have been taken and to please pick something else. The problem I'm running into is getting the result data in a usable form that I can then check the user-supplied data against.
I cut out the prepared statements for insertion from the snippit, as well as the validation routines, since both of them are working fine.
DB connection snippit
try {
if(!($dbc = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME))){ // Creates the $dbc variable object so we can
// have a connection to the database.
// uses mysqli functions.
throw new Exception;
}
}
catch (Exception $e) {
echo '<p>Could not connect to the database. Please contact the system administrator.</p>';
}
Snippit of Registration script
//before this was validation routines, if anything was wrong the script generated something into $reg_errors which is an array.
if(empty($reg_errors))
{
//queries database if there are any matches for username or email from user input.
if($stmt = $dbc->prepare("SELECT `email`, `username` FROM `users` WHERE `email` = ? OR `username` = ?"))
{
$stmt->bind_param("ss", $e, $u);
$stmt->execute();
$stmt->store_result();
$rows = $stmt->num_rows; //gives the number of rows returned from SELECT query. 0 means no dupes, 1 means one record has BOTH email and username, 2 means two different records (one with email, one with username)
##THIS IS WHERE I'M RUNNING INTO TROUBLE GETTING THE DATA IN A USABLE FORM##
$stmt->close();
} else {
echo "<p>Can't talk to database right now. Try again later, please.</p>";
}
if($rows==0) //no dupes of username or email, so let's try and add them into the DB
{
//prepared statement for insertion into DB
//also get's the count of affected rows. 1 means record inserted correctly.
//asks DB if a new row was created, and if so, thanks user for
//registration on the site & sends an email to their email.
//if query doesnt work, an error is triggered
if($count==1) {
//constructs a thank you note and emails it to the user, using the email they supplied.
exit();
} else {
echo "<p>Unable to process your registration at this time. Please try again later..</p>";
}
} else { // both username and email might be already used in DB, and error msgs are generated for array.
if($rows==2) { // this checks to make sure both entries are dupes
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
$reg_errors['username'] = 'This username has already been registered. Please try another.';
} else { //this checks to see which of the two (email or username) is already in DB if both arent dupes.
if((__NEED SOMETHING HERE FROM DB QUERY___ == $_POST['email']) && (__NEED SOMETHING HERE FROM DB QUERY___ == $_POST['username'])) { //both match entries in DB
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
$reg_errors['username'] = 'This username has already been registered with this email address. If you have forgotten your password, use the link to the right to have your password sent to you.';
} elseif(__NEED SOMETHING HERE FROM DB QUERY___==$_POST['email']) { // email match
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
} elseif(__NEED SOMETHING HERE FROM DB QUERY___==$_POST['username']) { // username match
$reg_errors['username'] = 'This username has already been registered. Please try another one.';
}
} // end of $rows==2 ELSE
} // end of $rows == 0 IF
} else { // end of empty reg_errors conditional
//do something if the reg_error array isnt empty..
}
i'm pretty sure the answer lies in iterations and using meta_data from the result mysqli object, but after beating my head against a wall for a couple days and pouring over the mysqli php manual pages like a maniac, I'm still no closer to figuring out what I should be doing. Could anyone point me in the correct direction?
Starting from the registration script, have you tried this:
if($stmt = $dbc->prepare("SELECT `email`, `username` FROM `users` WHERE `email` = ? OR `username` = ?"))
{
$stmt->bind_param("ss", $e, $u);
$stmt->execute();
$stmt->bind_result($email, $username);
$rows = $stmt->num_rows;
//Move Conditionals Up a Little
if( $rows == 0 ) { //If No Records are Found
//Continue Registration
}
else if( $rows == 1 ) { //If One Record is Found
$stmt->fetch();
//Do Something With $email and $username from DB Here
}
else { //If More than One Record is Found
while( $stmt->fetch() ) { //Iterate Through Records
//Do Something With $email and $username from DB Here
}
}
}

PHP Form - Check if mysql already contains email data

This register form was made by me, but it doesn't do what I want it to do.
I want it to connect to a mysql database and store the information that was given by the form. I want it to hash the $password in md5 and store it in the "gebruikers" table. Please don't reply with "Damn, you have no idea what you are doing" or something like that. I am learning PHP by looking to examples and following tutorials. Please keep in mind that the mysql insert code is not filled in right, because I got stuck a few lines above.
So, my question is: I want to check if the mysql table already contains $email. If it IS already in the mysql table, I want to display an error message that I can place somewhere else in my PHP page. If the email adress given is unique, than the $password should hash into md5 and store into the mysql database, just like the other form entries.
How do I do that?
<?php
// Fetching all the form details
$email = $_POST["email"];
$password = $_POST["password"];
$voornaam = $_POST["voornaam"];
$tussenvoegsel = $_POST["tussenvoegsel"];
$achternaam = $_POST["achternaam"];
$dag = $_POST["dag"];
$maand = $_POST["maand"];
$jaar = $_POST["voornaam"];
$straat = $_POST["straat"];
$postcode = $_POST["postcode"];
$woonplaats = $_POST["woonplaats"];
$cniveau = $_POST["cniveau"];
$oniveau = $_POST["oniveau"];
$voornaam = $_POST["voornaam"];
$aboutme = $_POST["aboutme"];
//Here's where I don't know how to continue
$check = mysql_query("SELECT * FROM `gebruikers` WHERE `email` = '$email'");
if($check === FALSE) {
//there is a user already registered
echo("$email is al in gebruik. <a href='login.php'>Inloggen</a>?");
} else {
//There isn't a username
//mysql_query("INSERT INTO `user` (`id` ,`username` ,`password`) VALUES (NULL , '{$_POST['email']}', MD5( '{$_POST['password']}' ))");
echo("You have been registered!");
}
P.S.: I'm not a native English speaker, so please ignore my grammar mistakes/typos.
First of all, you made a major mistake: There is a SQL-Injection security hole.
Please read this: http://php.net/manual/en/security.database.sql-injection.php
Second, you should use mysqli instead of mysql, because mysql is deprecated.
Your error is that SQL does only return false if the query is invalid, not if there are no results. So the correct way of checking if there are results is to use http://php.net/manual/en/mysqli-result.num-rows.php
$result = mysql_query("SELECT * FROM `gebruikers` WHERE `email` = '$email' LIMIT 1");
if(mysql_fetch_array($result) !== false)
{
...
} else {
....
}
You should also read up on preventing SQL injection.
Maybe you've forgot to set the mysql_connect statement.
But I strongly recommend you stick from now on, with the mysqli_ functionality, since, as Aragon0 said, mysql is deprecated in PHP's newest versions.
Besides, mysqli statements are simpler than the mysql ones, for example you use one statement (mysqli_connect) to connect to your host and select your database at the same time, instead of using separated statements (both mysql_connect and mysql_select_db).
Oh, and no additional service package is required to use it. :)

mysqil_real_escape_string() error I can't fix

Although the item is successfully added to the database, I'm not sure that I'm executing the mysql_real_escape_string() function correctly and, thus, getting the error. Any help is appreciated.
Success!
Warning: array_map() [function.array-map]: Argument #2 should be an array in /home/site4/public_html/lab/mailing_list_dev_1-0/mailing_list_add.php on line 32
Thanks for signing up!
Here's the code in question...
<?php
// connects the database access information this file
include("mailing_list_include.php");
// the following code relates to mailing list signups only
if (($_POST) && ($_POST["action"] == "sub")) {
if ($_POST["email"] == "") {
header("Location: mailing_list_add.php");
exit;
} else {
// connect to database
doDB();
// filtering out anything that isn't an email address
if ( filter_var(($_POST["email"]), FILTER_VALIDATE_EMAIL) == TRUE) {
echo 'Success!';
} else {
echo 'Invalid Email Address';
exit;
}
// check that the email is in the database
emailChecker($_POST["email"]);
// get number of results and do action
if (mysqli_num_rows($check_res) < 1) {
// free result
mysqli_free_result($check_res);
// cleans all input variables at once
$email = array_map("mysqli_real_escape_string", ($_POST["email"]));
// add record
$add_sql = "INSERT INTO subscribers (email)
VALUES('".$_POST["email"]."')";
$add_res = mysqli_query($mysqli, $add_sql)
or die(mysqli_error($mysqli));
$display_block = "<p>Thanks for signing up!</p>";
// close connection to mysql
mysqli_close($mysqli);
} else {
// print failure message
$display_block = "You're email address, ".$_POST["email"].", is already subscribed.";
}
}
}
?>
<html>
<?php echo "$display_block";?>
</html>
You're treating $_POST['email'] as an array, which it probably ins't.
If you only intended to escape email, do
$email = mysqli_real_escape_string($dbConn, $_POST['email']);
Then in your INSERT statement, use the escaped $email instead of $_POST['email']
$add_sql = "INSERT INTO subscribers (email) VALUES('$email')";
array_map() is meant for arrays. If all you have is a single value then just call the function directly.
There is at least one bug, here:
// Does not work because $_POST["email"] is a string, not an array
$email = array_map("mysqli_real_escape_string", ($_POST["email"]));
This looks like something you adapted from code that was working, but right now it's broken. You probably wanted something like this:
$post = array_map("mysqli_real_escape_string", $_POST["email"]);
after which you can use $post["email"] safely, as it has been escaped.
Of course escaping everything inside $_POST is possibly not the best way to go about this. There's still the mundane but spot-on way to consider:
$email = mysqli_real_escape_string($_POST['email']);
This is apparently not mysqli_real_escape_string problem but array_map() problem. Or rather misuse of the latter one.
However, you will face mysqli_real_escape_string() problem as soon as you solves this one.
To solve this latter your doDB() function have to return connection id, which you have to use with every mysqli_* function.
$conn = doDB();
$email = mysqli_real_escape_string($conn,$_POST["email"]);
thus you will have all your [listed] problems solved but I believe that emailChecker will may cause the same kind of problem of inexistent $check_res variable. Instea d of which such a function apparently have to return just a boolean and used like
if (!emailChecker($_POST["email"])) {

Categories