Create an exception in PHP and PDO to prevent duplicates - php

Hello Stackoverflow community,
I'm starting to work with PDO soon. I have a trivial question that I do not know how to solve. So, let me know if you guys can help me.
I have a form that aims to update data from a user account in a member space. This form has three fields "Last Name", "Name" and "E-mail".
I don't want that the user register and existing e-mail. However, if the user does not want to update their email and only wants to change the "Last Name" and "Name" fields, the PHP code must allow updating the records in the database.
I created a function to process the form. It is able to prevent the insertion of duplicate records, but it has a problem. If the user does not want to update their email, the function returns that there is already an equal email in the database. In fact, email already exists, so I would like to know how to implement this exception in my code to allow it to update the records when the user does not want to change their e-mail?
Below the function:
function update_admin_profile() {
session_start();
if (isset($_SESSION['id']) AND isset($_SESSION['login'])) {
// get the session variables for another propouse.
$id = $_SESSION['id'];
$pseudo = $_SESSION['login'];
// p - It's the URL parameter. anti_sql_injection is a function to check the parameter.
$p = anti_sql_injection($_GET['p']);
if (isset($_POST['last_name']) AND isset($_POST['name']) AND isset($_POST['email'])) {
$bdd = connexion_bdd();
$query = $bdd->prepare('SELECT * FROM tbl__administrators WHERE email = :email');
$query->execute(array('email' => htmlspecialchars($_POST['email'])));
$count=$query->rowCount();
if ($count == 0 ) {
$update = $bdd->prepare('UPDATE tbl__administrators SET last_name = :last_name, name = :name, email = :email WHERE id = ' . $p);
$update->execute(array(
'last_name' => htmlspecialchars($_POST['last_name']),
'name' => htmlspecialchars($_POST['name']),
'email' => htmlspecialchars($_POST['email'])
));
//The profile was updated.
header('Location: notify.php?m=49');
} else {
//The e-mail already exists!
header('Location: notify.php?m=48');
}
} else {
//Please fill in all fields
header('Location: notify.php?m=41');
}
} else {
//You session is expired. You will be disconnected now. Please, perform the login again and repeat this operation.
header('Location: notify.php?m=7');
}
}
Note: It's function works if I change the e-mail.
Thank you so much for your help.
Have nice day.

If the user does not want to update their email, the function returns that there is already an equal email in the database.
It's very simple. Just add another condition to exclude the current user from the query results
$query = $bdd->prepare('SELECT 1 FROM tbl__administrators WHERE email = ? and id != ?');
$query->execute(array($_POST['email'], $id));

Related

How to use php to search if element already exists in mysql db

I've got a website and when a user registers I want to check, if the entered email has already been used to register another account.
database: users
row: email
new email: $email_register
$result = $pdo->prepare("IF email_register = ? IN email FROM users $same = TRUE");
$result->execute(array($email_register));
$user = $result->fetch();
if($same == TRUE)
{
echo email already used;
}
else
{
#continue registration process
}
I want a way to know if the email is already in the db, and if it is, for the user to be sent back to the registration page with an error message (error code transmitted via header).
Assuming that users should not have more than one account per email, an easy approach is to make the email column a unique key (or primary key) in the users table. This prevents an email being used more than once.
Try this way
// check if email is taken already
$stmt = $pdo->prepare("SELECT email FROM users WHERE email_register = :email");
$stmt->execute([
'email_register ' => $email
]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (isset($user) && !empty($user)){
// Username already taken
echo "email already used";
}else{
//redirect to registration process
}
There is no need for IF in the SQL query. Just write simple select statement like:
Select email from users where email = 'example#example.com';
if query return and result it means the email is already in database if not then you can continue to the registration process.
if($exist)
{
return false; or you redirect to registration page whatever you want to do.
}
#continue registration process

Directing user to a page or another (PHP and MysQL)

I am creating a site where invited users will be directed to a register once their email is validated against a master list of users and (2) returning users will be directed to a different page once validated against a master list of users. Initially the master list of users will only have email addresses for the invited users. Upon registration, users will enter the rest of the information, including First Name (fname).
What I need to do with this piece of code is check if the first name is NULL, if so direct user to "registration.html"; whereas if a first name is present for that user then the user should be directed to "overview.html".
My code is clearly not working properly, as regardless of fname being NULL or XYZ users are directed to "overview.html".
$query = "SELECT email, fname FROM registration WHERE email='$email'";
if (fname = "NULL") {
header('location: registration.html');
} else {
header('location: overview.html');
}
Thanks for your help!
I'm assuming you didn't paste the whole code here. How did you fetch the row?
One thing I can point out though, in PHP = is assignment.You want to use == which is the comparison operator.
Also, unquote "NULL", as you're currently comparing it to a string 'null'.
Hope that solves it.
EDIT: seeing your other comments, here's what the code should look like, assuming you have the email stored in a variable called $email and a PDO connection stored in $dbc.
$q = "SELECT email, fname FROM registration WHERE email = ?";
$stmt = $dbc->prepare($q);
$stmt->execute(array($email));
if($stmt->rowCount() == 1){ //you probably have unique email accounts
$row = $stmt->fetch();
if (is_null($row['fname'])) {
header('location: registration.html');
} else {
header('location: overview.html');
}
}

adding a column in mysql so that depending on which user logs in they go to a specific page

below is the authorisation script (from login). I want to send a user to a specific page depending on (new column called company to be added to database table) a user and their company.
Current script, even if someone can point me in the direction I would appreciate it:
<title>authorise</title>
<?php
session_start();
$un = $_POST['username'];
$pw = $_POST['password'];
if ($pw != ''){
$_SESSION['user'] = $un;
echo "Incorrect username / password";
}
try
{
$dbh = new PDO("mysql:host=localhost;dbname=login_site","root","black$23");
}
catch (PDOException $e){
echo $e->getMessage();
}
$query = "SELECT * FROM users WHERE LOWER(username)=:username";
$stmt=$dbh->prepare($query);
$stmt->bindValue(':username',strtolower ($_POST['username']));
$stmt->execute();
if ($stmt->rowCount() == 1)
{
$row=$stmt->fetch(PDO::FETCH_ASSOC);
require('blowfish.php');
require('bcrypt.class.php');
$bcrypt = new Bcrypt(4);
if($bcrypt->verify($_POST['password'],$row['password']))
{
echo"logged in!!";
header("Location: hollyfort/123.php");
}
}
?>
I think you need a table with the userID and a page id (or perhaps w/ the companyID and a pageID), so you can determine the page to be returned by the user or company. Maybe you even want both tables, e.g. if you want all employees of a company to get a certain site, but the CEO should get to a special site where he can see all his employees' activities.
you then first check, if an entry for that user exists (if it does, you return the page). if not, check if an entry for the company exists. if you cannot find an entry, you probably want to return a default page
all is ok - I setup company variables to check against the database column and it works :)

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
}
}
}

mysql_affected_rows() work-around?

I'm using this code as part of an email confirmation script. It works great, except I can't figure out a way to distinguish between when somebody has provided an invalid email address vs when they have simply refreshed the page (ie. already confirmed their account). The only think I can think of is putting a time stamp field in the users table that always gets updated, but I'm hoping there is a better way. I thought REPLACE would do the trick, but, while email is unique, it is not the primary key.
if (isset ($email, $token, $correctToken)){
$success = FALSE; //Set the $success variable so that we don't get an error when testing for it later
if ($token == $correctToken) {
$confirm = mysql_query("UPDATE users
SET conf = 'TRUE'
WHERE email = '$email'");
if (mysql_affected_rows() == 1) {
echo "Thank you! Your email address is confirmed and your account is actived.";
$success = TRUE;
}
}
if (!$success) {
echo "There was a problem with the confirmation. Try the link in your email again or contact us at Support#WiseRenters.com";
// Send email to admin to notify of error
exit;
}
}
Thanks in advance for the advice!
Billy
EDIT: The $email and $token variables are provided through $_GET or $_POST, in case that wasn't obvious.
A redirection would stop them from refreshing - but what if they click the link in their email again?
You should check if the current user is activated or not.
$sql = "SELECT id, conf FROM users WHERE email = '{$email}'";
$exec = mysql_query($sql) or die(mysql_error());
list( $id, $conf ) = mysql_fetch_row($exec);
if( $conf ) {
// Redirect them to their profile with a message saying "your account has already been activated"
header("Location: /profile?already_activated");
exit;
}
// your code
$confirm = mysql_query("UPDATE users
SET conf = 'TRUE'
WHERE id = '{$id}'");
In response to your comment:
Keep in mind this will only add an additional query for a user who has not activated yet. If they have activated then the redirect occurs and the page is still running only 1 query.
To optimize this a bit, you can select the user ID and confirmation status based on the email address. Then, if they do need to be activated, you can activate them based on user ID instead of email. Since an integer key is much faster, the combined time of the 2 queries will be about the same as the 1 query where you are updating based on a string column. I updated the code to reflect this.
Also, this page will probably not be accessed very frequently. Any optimizations from here would really be micro- and not really that helpful.
By the way I hope you are using mysql_real_escape_string on the email, and that conf is a boolean true/false not a string 'true'/'false'.

Categories