PDO database insert - php

hi i have a table in mysql have six fields
ID, mobileNumber, firstName, lastName, email, password , rollID
ID is autoincrement and i want to insert to it using php
php code
public function run($firstName, $lastName, $mobileNumber, $email, $password, $rePassword) {
if (!$this->db->isExistedMobile($mobileNumber)) {
try {
$query = "INSERT INTO user (firstName, lastName, mobileNumber, email, password, rollID)
VALUES (:firstName, :lastName, :mobileNumber, :email, :password, 'rollID')";
$sth = $this->db->prepare($query);
$sth->execute(array(
':firstName' => $firstName,
':lastName' => $lastName,
':mobileNumber' => $mobileNumber,
':email' => $email,
':password' => $password,
':rollID' => "roma"
));
header("location: " . URL . "index");
} catch (PDOException $e) {
die($e->getMessage());
exit;
}
} else {
include 'controlers/Error.php';
$error = new Error();
$error->index("you enterd a used mobile number");
}
}
i have this exception
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
the function isExistedMobile always return false so don't worry about it , i don't know where is the wrong , is it in the syntax ? or in the rollID cos i make it static ?
thank you for helping :)

The problem (with your original code) was that the parameter array had a trailing comma, which created an additional null element within it.
I'd recommend reverting to that version (with the literal value for rollID) as originally intended, but make sure you remove the trailing comma after $password:
public function run($firstName, $lastName, $mobileNumber, $email, $password, $rePassword) {
if (!$this->db->isExistedMobile($mobileNumber)) {
$query = "INSERT INTO user (firstName, lastName, mobileNumber, email, password, rollID)
VALUES (:firstName, :lastName, :mobileNumber, :email, :password, 'ddd')";
$sth = $this->db->prepare($query);
$sth->execute(array(
':firstName' => $firstName,
':lastName' => $lastName,
':mobileNumber' => $mobileNumber,
':email' => $email,
':password' => $password // , removed from here
));
header("location: " . URL . "index");
} else {
include 'controlers/Error.php';
$error = new Error();
$error->index("you enterd a used mobile number");
}
}

Related

Where should I add the code so that it checks whether email exists or not?

Where should I add the code so that it checks whether email exists or not? I have inserted all my details inside an array how should i call the specific attribute and where should i implement it so that it check whether more then one email exists on my databse or not?
<?php
$connect = new PDO("mysql:host=localhost;dbname=testing", "root", "");
$message = '';
if(isset($_POST["email"]))
{
sleep(3);
$query = "
INSERT INTO tbl_login
(first_name, last_name, gender, email, password, address, mobile_no) VALUES
(:first_name, :last_name, :gender, :email, :password, :address, :mobile_no)
";
$password_hash = password_hash($_POST["password"], PASSWORD_DEFAULT);
$user_data = array(
':first_name' => $_POST["first_name"],
':last_name' => $_POST["last_name"],
':gender' => $_POST["gender"],
':email' => $_POST["email"],
':password' => $password_hash,
':address' => $_POST["address"],
':mobile_no' => $_POST["mobile_no"]
);
$statement = $connect->prepare($query);
if($statement->execute($user_data))
{
$message = '
<div class="alert alert-success">
Registration Completed Successfully
</div>
';
header("location:login.php");
}
else
{
$message = '
<div class="alert alert-success">
There is an error in Registration
</div>
';
}
}
?>
You could write an if statement which executes a query and Stores
the resulting value to a variable. Now if that variable is null it means database does not have the same email registered already.
$sql = 'SELECT email from tbl_login WHERE email=:email'
$params = [
:email => $_POST['email']
] ;
// Now the if statement which checks if the entered email already exists in the DB
$stmt = $connect->prepare($sql)
$stmt->execute($params)
if(!$temp = $stmt->fetc())
{ // Email doesn't exist in the DB, procees to insert it}
else
{ // Email already exists in the DB}

Unable to INSERT a row in a table with PDO

I want to insert some data into a table using PDO. I looked for some examples and I found that I need to use the functions prepare, bind and then execute, however I can not figure out in my code what I am doing wrong because it inserted nothing and I have no error in the query or php code.
if($_POST){
$account = $_POST['account'];
$password = $_POST['password'];
$phone = $_POST['phone'];
$email = $_POST['email'];
$stmt = 'INSERT INTO employer(account, password, phone, email) VALUES(:account, :password, :phone, :email)';
$stmt = $conn->prepare($stmt);
$stmt->bindParam(':account', $account, PDO::PARAM_STR,100);
$stmt->bindParam(':password',$password, PDO::PARAM_STR,100);
$stmt->bindParam(':phone', $phone, PDO::PARAM_STR,100);
$stmt->bindParam(':email', $email, PDO::PARAM_STR,100);
if ($stmt->execute(array('account' => $account,
'password' => $password,
'phone' => $phone,
'email' =>$email
)
)
){
echo "success";
}else{
echo "error";
}
}
Error detected by #jeroen I was binding twice. So I can bind "either bind before the execute statement or send an array as a parameter, not both"
$stmt = $pdo->prepare('
INSERT INTO employer
(account, password, phone, mail)
values (:account, :password, :phone, :mail)');
$stmt->execute(
array(':account' => $account,
':password' => md5($password),
':phone' => $phone,
':mail' => $email
)
);
if ($pdo->lastInsertId())
return true;
else
return false;

Quick PHP Variable guidance

I'm a newbie with PHP. I am trying to create a log in /register system for a project, so I am using a login system source code I found which has many functions and features like salted passwords. The system itself works fine, but I am trying to add more fields to my MySQL Table. The system had an array for extra columns, but I think it was resulting in bad mysql syntax so I decided to write out the query myself using the variables, but I am not sure how I can give access to the variables to the function. The variables are in the register.php document, here is the code (all of register.php):
if( isset($_POST['submit']) ){
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$user = $_POST['username'];
$sex = $_POST['sex'];
$country = $_POST['strCountryChoice'];
$email = $_POST['email'];
$pass = $_POST['pass'];
$pass2 = $_POST['pass2'];
$birthdate = $_POST['birthdate'];
$created = date("Y-m-d H:i:s");
//need to add a lot more validation functions.. AKA Check if email exists and username. Password > 5 chars
if( $user=="" || $email=="" || $pass=='' || $pass2=='' || $firstname=='' || $lastname='' || $sex='' || $country='' || $birthdate='' ){
echo "Fields Left Blank","Some Fields were left blank. Please fill up all fields.";
exit;
}
if( !$LS->validEmail($email) ){
echo "E-Mail Is Not Valid", "The E-Mail you gave is not valid";
exit;
}
if( !ctype_alnum($user) ){
echo "Invalid Username", "The Username is not valid. Only ALPHANUMERIC characters are allowed and shouldn't exceed 10 characters.";
exit;
}
if($pass != $pass2){
echo "Passwords Don't Match","The Passwords you entered didn't match";
exit;
}
$createAccount = $LS->register($user, $pass,
array(
"email" => $email,
"name" => $firstname,
"lastname" => $lastname,
"gender" => $sex,
"country" => $country,
"DOB" => $birthdate,
"created" => date("Y-m-d H:i:s") // Just for testing
)
);
if($createAccount === "exists"){
echo "User Exists.";
}elseif($createAccount === true){
echo "Success. Created account.";
}
}
The whole system takes place in another file which has the class. Here is the register function:
public function register( $id, $password, $other = array() ){
if( $this->userExists($id) && (isset($other['email']) && $this->userExists($other['email'])) ){
return "exists";
}else{
$randomSalt = $this->rand_string(20);
$saltedPass = hash('sha256', "{$password}{$this->passwordSalt}{$randomSalt}");
if( count($other) == 0 ){
/* If there is no other fields mentioned, make the default query */
//old query: ("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`) VALUES(:username, :password, :passwordSalt)");
//new query: ("INSERT INTO `{$this->dbtable}` (`username`, 'email' , `password`, `password_salt` , 'name' , 'lastname' , 'gender' , 'country' , 'DOB') VALUES(:username, :email, :pass, :passwordSalt, :firstname, :lastname, :gender, :country, :DOB)");
$sql = $this->dbh->prepare("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`) VALUES(:username, :password, :passwordSalt)");
}else{
/* if there are other fields to add value to, make the query and bind values according to it */
//old query: ("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`, $columns) VALUES(:username, :password, :passwordSalt, :$colVals)");
//new query: ("INSERT INTO `{$this->dbtable}` (`username`, 'email' , `password`, `password_salt` , 'name' , 'lastname' , 'gender' , 'country' , 'DOB') VALUES(:username, :email, :pass, :passwordSalt, :firstname, :lastname, :gender, :country, :DOB)");
$keys = array_keys($other);
$columns = implode(",", $keys);
$colVals = implode(",:", $keys);
//l= $this->dbh->prepare("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`, $columns) VALUES(:username, :password, :passwordSalt, :$colVals)");
//INSERT INTO MyGuests (firstname, lastname, email)cLUES ('John', 'Doe', 'john#example.com')
$sql = $this->dbh->prepare("INSERT INTO `{$this->dbtable}` (username,email,password,password_salt,name,lastname,created,gender,country,DOB) VALUES ('$username','$email','$pass','$saltedPass','$firstname','$lastname','$created','$gender','$country','$birthdate')");
print($sql);
foreach($other as $key => $value){
$value = htmlspecialchars($value);
$sql->bindValue(":$key", $value);
}
}
/* Bind the default values */
$sql->bindValue(":username", $id);
$sql->bindValue(":password", $saltedPass);
$sql->bindValue(":passwordSalt", $randomSalt);
$sql->execute();
return true;
}
}
So I need to use the variables from register.php in the class file. Can I just include it at the top or do I need to do something specific to the function?
Thanks. I'm focusing on the $sql line after else.
Yes you can include/require register.php file in the class file to use all the variables.
On another note i would like to mention that you should always filter out the POST data before adding it to the query for security concerns.

Preventing TOCTTOU (Time of check to time of use)

I have been learning about making an authentication system more secure. One of the problems with my code is that it is vulnerable to a Time of check to time of use bug. Here is my code:
$stmt = $connection->prepare("SELECT username, password, email FROM users WHERE username=:username");
$stmt->execute(array(':username' => $username));
$rows = $stmt->fetch(PDO::FETCH_ASSOC);
if ($rows != null) {
$_SESSION["message"] = "name already exists";
} else {
$stmt = $connection->prepare("INSERT INTO users(company, username, password, first_name, last_name, address, address2, city, state, zip, phone, email) VALUES (:company, :username, :password, :first_name, :last_name, :address, :address2, :city, :state, :zip, :phone, :email)");
$result = $stmt->execute(array(':company' => $company, ':username' => $username, ':password' => $hashed_password, ':first_name' => $firstName, ':last_name' => $lastName, ':address' => $address1, ':address2' => $address2, ':city' => $city, ':state' => $states, ':zip' => $zip, ':phone' => $phone, ':email' => $email));
if ($result) {
// Success
$_SESSION["message"] = "You've successfully registered.";
redirect_to("login.php");
} else {
// Failure
$_SESSION["message"] = "Registration failed.";
}
}
}
} else {
// This is probably a GET request
}
So, it is first seeing if the user exists and if not, then to go ahead and insert the user's information into the database. But this creates a vulnerability for TOCTTOU. To fix this, I made the 'username' column UNIQUE. Is this the only thing I need to do? Is there a way to combine these two statements so it isn't vulnerable to that type of attack?
I've been reading resources on this and it seems making the column UNIQUE or PRIMARY is the best option. But, I don't want to rely on the database. Any suggestions? Thanks!
Here is my fixed code:
At top of file:
ini_set('display_errors', 'On'); error_reporting(E_ALL);
Then:
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$connection->beginTransaction();
try {
$stmt = $connection->prepare('SELECT 1 FROM users WHERE username = :username LIMIT 1');
$stmt->execute([':username' => $username]);
$check = $stmt->fetchColumn();
if ($check) {
$_SESSION["message"] = "name already exists";
} else {
$stmt = $connection->prepare('INSERT INTO users(company, username, password, first_name, last_name, address, address2, city, state, zip, phone, email) VALUES (:company, :username, :password, :first_name, :last_name, :address, :address2, :city, :state, :zip, :phone, :email)');
$stmt->execute(array(':company' => $company, ':username' => $username, ':password' => $hashed_password, ':first_name' => $firstName, ':last_name' => $lastName, ':address' => $address1, ':address2' => $address2, ':city' => $city, ':state' => $states, ':zip' => $zip, ':phone' => $phone, ':email' => $email)); // this should throw an exception if it fails, no need to check the return value
$_SESSION["message"] = "You've successfully registered.";
}
$connection->commit();
redirect_to("login.php");
} catch (PDOException $e) {
$connection->rollBack();
throw $e;
}
I would maintain the unique constraint on your table as that makes sense from a data perspective.
For your PHP code, simply use transactions. For example...
// make sure you have $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
$connection->beginTransaction();
try {
$stmt = $connection->prepare('SELECT 1 FROM users WHERE username = :username LIMIT 1');
$stmt->execute([':username' => $username]);
$check = $stmt->fetchColumn();
if ($check) {
$_SESSION["message"] = "name already exists";
} else {
$stmt = $connection->prepare('INSERT INTO ...');
$stmt->execute([...]); // this should throw an exception if it fails, no need to check the return value
$_SESSION["message"] = "You've successfully registered.";
}
$connection->commit();
redirect_to("login.php");
} catch (PDOException $e) {
$connection->rollBack();
throw $e;
}

Not Submitting to database, with php, mysqli

I can not figure out why it is breaking after passing validation and not submitting to database. Just comes up with blank screen. I have echoed out the new_password and it is encrypting it properly. Am I missing something? or doing something wrong? Any help/advice is appreciated. thanks in advance.
if (isset($_POST['register'])){
//Validation and post variable stuff here but doesn't appear to be any issue with it as I have tested it alot.
}
else if(!$error_msg && !$returned_record && $_POST['register']){
function generateHash($password_1){
if(defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH){
//echo "WE HAVE CRYPT BLOWFISH";
$salt = '$2y$11$'. substr(md5(uniqid(rand(), true)), 0, 22);
return crypt($password_1, $salt);
}//End If
}//End Function generateHash();
$new_password = generateHash($password_1);
//Build our query
$sql = ("INSERT INTO members (username, email, first_name, last_name, country, password_1) VALUES (?,?,?,?,?,?)");
//Prepare our query
$stmt = $mysqli->prepare($sql) or die("PREPARE DIDNT WORK");;
//Bind the fields and there parameters to our query
$stmt->bind_param('ssssss', $username, $email, $first_name, $last_name, $country, $new_password);
//Execute the query
$stmt->execute();
header('Location: http://someurl.com');
exit();
}
Instead of binding the parameters, try this:
$sql = ("INSERT INTO members (username, email, first_name, last_name, country, password_1) VALUES (:username, :email, $first_name, :last_name, :country, :password_1)");
$stmt = $mysqli->prepare($sql) or die("Failed Execution");;
$stmt->execute(array(
':username' => $username,
':email' => $email,
':first_name' => $fname,
':last_name' => $lname,
':country' $country,
':password_1' $password
));
I think i have figured out. I was trying to implement this code into a wordpress template page with a custom loop. I removed all loop/functions and It worked first try. So something in there was causing the issues. Thanks for trying!

Categories