I'm running an insert query to insert user information into the database.
The fields to insert are username and email, and the email field is not mandatory.
The query run fine when the input includes the email, but when I entered nothing in the email, the PDO error always reports the error " Duplicate entry '' for key 'email' " .
$post = $this->input->post();
$sql = "INSERT INTO users (username, email) VALUES (:username, :email)";
$query = $this->db->conn_id->prepare($sql);
$query->bindValue (':username', $post['username'], PDO::PARAM_STR);
if ($email == false){
$query->bindValue(':email', '', PDO::PARAM_STR );
} else {
$query->bindValue(':email', $post['email'], PDO::PARAM_STR );
}
$query->execute();
First, as I mentioned in the comment, you need to set the email column to allow for null values. If you are not requiring an email address, then it is better to store a non-email as null rather than an empty string - but in this case it is necessary because the column is unique.
Then, try this code:
$post = $this->input->post();
if (!$post['email']){
$post['email'] = NULL;
}
$sql = "INSERT INTO users (username, email) VALUES (:username, :email)";
$query = $this->db->conn_id->prepare($sql);
$query->execute(array($post['username'], $post['email']));
Related
I have a register, were people can register with their username, their email and a password. If this gets successfully transmitted to the database, this data will be inserted into a table called users. Now, I need the last ID from the just registered user for a second table that is called users_tokens, where I obviously want to save a token for every specific user. I've tried to solve this by using $mysql->insert_id; but that returns 0 in the table and I am also curious if this is a safe method since through my websites data gets inserted all the time.
My PHP Script:
$key = getToken(32);
$token = bin2hex(openssl_random_pseudo_bytes(64));
$stmt = $mysql->prepare("INSERT INTO users (name, email, password, verification_key, register_date) VALUES(?,?,?,?,?)");
$stmt->bind_param("sssss", $_POST["name"], $_POST["email"], md5($_POST["password"]), $key, $posted_on);
$lastid = $mysql->insert_id;
$u_token = $mysql->prepare("INSERT INTO users_tokens (uid, token) VALUES(?,?)");
$u_token->bind_param("ss", $lastid, $token);
Any suggestions?
You just need to execute your statement before retrieving insert_id, something like this
$stmt = $mysql->prepare("INSERT INTO users (name, email, password, verification_key, register_date) VALUES(?,?,?,?,?)");
$stmt->bind_param("sssss", $_POST["name"], $_POST["email"], md5($_POST["password"]), $key, $posted_on);
$stmt->execute(); //You should check for correct execution
$lastid = $mysql->insert_id;
So I have 2 tables:
users with columns id (primary, auto_increment), username, password, person_id (foreign key)
people with columns id (primary, auto_increment), first_name, last_name
What I'm trying to do is when registering a new account have a new row inserted into people and then have a new row inserted into users with the people.id as foreign key users.person_id.
Right now I have 2 php functions that get executed right after eachother, firstly one with this query:
insert into people (first_name, last_name) values (:firstname,
:lastname)
Secondly one with this query:
insert into users (username, password, person_id) values (:user,
:pass, LAST_INSERT_ID())
All of this works fine except for the fact that last_insert_id() keeps giving value 0 instead of the id from the previous query. Is it maybe not possible to use last_insert_id() when using 2 separate queries? If so what would be the best way to go about it then?
This is my relevant php code:
//make new person
$newPerson = new PeopleManagement();
$pm = $newPerson->createNewPerson($_POST["firstName"], $_POST["lastName"]);
//make new user
$newUsr = new Authentication();
$ac = $newUsr->registerNewUser($_POST["user"], $_POST["pass"]);
public function registerNewUser ($user, $pass) {
try {
$dbm = new PDO(DBCONFIG::$db_conn, DBCONFIG::$db_user, DBCONFIG::$db_pass);
$dbm->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbm->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
hash = password_hash($pass, PASSWORD_DEFAULT);
$sql = "insert into users (username, password, person_id) values (:user, :pass, LAST_INSERT_ID())";
$stmt = $dbm->prepare($sql);
$stmt->execute(array(
':user' => $user,
':pass' => $hash
));
$dbm = null;
} catch(PDOException $ex) {
return "Could not connect to database";
}
}
public function createNewPerson($firstName, $lastName) {
$dbm = new PDO($this->dbConn, $this->dbUser, $this->dbPass);
$sql = "insert into people (first_name, last_name) values (:firstname, :lastname)";
$stmt = $dbm->prepare($sql);
$stmt->execute(array(
':firstname' => $firstName,
':lastname' => $lastName
));
$dbm = null;
}
This question already has answers here:
Insert_id is null when used directly in next prepared statement
(2 answers)
Closed last year.
I want to do more than one database queries in the same file:
Create a user, select the UID of that newly created user, and assign to that same user a specific role.
After I get the UID from the newly created user I save that value into the $userID variable, but at the end of the file, the variable value gets lost.
Why? (PS: I'm not taking into account security at the moment).
//Create User
$email = strip_tags($_POST['email']);
$conectar = mysqli_connect(HOST, USER, PASS, DATABASE);
$query = "INSERT INTO usuarios
(userEmail)
VALUES
('$email')";
$insertarBase = mysqli_query($conectar,$query);
mysqli_close($conectar);
//look for the UID of the newly created user
$conectar2 = mysqli_connect(HOST, USER, PASS, DATABASE);
$buscarUsuario = "SELECT userID, userEmail
FROM usuarios
WHERE userEmail='$email'
";
$resultadoBusqueda = mysqli_query($conectar2,$buscarUsuario);
$row = mysqli_fetch_array($resultadoBusqueda);
$userID = $row['userID'];
mysqli_close($conectar2);
//assign a role to the newly created user
$conectar3 = mysqli_connect(HOST, USER, PASS, DATABASE);
$asignarRol = "INSERT INTO rolesUsuarios
(userID, nombreRol)
VALUES
('$userID', 'registered')
";
$asignarRolenBase = mysqli_query($conectar3,$asignarRol);
mysqli_close($conectar3);
echo $userID; //Here the content of $userID is gone, nothing gets printed out
Edited:
For some weird reason, $userID = mysqli_insert_id($conectar); returns zero.
The creation of the usuarios table statement is this:
CREATE TABLE usuarios(
userID int unsigned not null auto_increment primary key,
userEmail char(50) not null);
Also, echo $asignarRol; returns:
INSERT INTO rolesUsuarios (userID, nombreRol) VALUES ('0', 'noAutorizado')
i tried to tidy up your code and delete superfluous code.
//Create User
$email = $_POST['email']; // you have to verify if this is an email or html etc.
$conectar = new mysqli(HOST, USER, PASS, DATABASE);
$query = "INSERT INTO usuarios
(userEmail)
VALUES
(?)";
$stmt = $conectar->prepare($query);
$stmt->bind_param('s',$email);
$stmt->execute();
$userID = $stmt->insert_id;
$stmt->close();//close statement
//assign a role to the newly created user
$query = "INSERT INTO rolesUsuarios
(userID, nombreRol)
VALUES
(?, 'registered')";
$stmt = $conectar->prepare($query);
$stmt->bind_param('i',$userID);
$stmt->execute();
$stmt->close();
$conectar->close();
echo $userID; //Here the content of $userID
First of all , you don't have to create a new db-connection for each statement.
Second: please prepare your statements - for security purposes.
If $userID is empty, make an error_log($userID); after you $userID gets it value, if it's empty , there might be something else wrong.
First as other said to you use prepared statement for SQL injection and second the SQL connection not need to repeat so many time. Too many code and select not need please check the follow.
<?php
$conn = new mysqli(HOST, USER, PASS, DBNAME);
$insert_usuarios = $conn->prepare(" INSERT INTO usuarios ( userEmail ) VALUES ( ? ) ");
$insert_usuarios->bind_param( "s", $userEmail);
$insert_rolesUsuarios = $conn->prepare(" INSERT INTO rolesUsuarios ( userID, nombreRol ) VALUES ( ?, ? ) ");
$insert_rolesUsuarios->bind_param( "is", $userID, $nombreRol);
if(isset($_POST['email'])) {
$userEmail = $_POST['email'];
if (!$insert_usuarios->execute()) { // ERROR
echo('Error'); // OR ACTION THAT YOU LIKE
} else { // SUCCESS
$userID = $insert_usuarios->insert_id; // LAST ID INSERT
$nombreRol = 'REGISTERED';
if (!$insert_rolesUsuarios->execute()) { // ERROR
echo('Error'); // OR ACTION THAT YOU LIKE
} else { // SUCCESS
echo('Done!');
}
}
}
?>
Cheers!!!
Yet another cleanup of your code, following your code style and convention =)
//Create User
$conectar = mysqli_connect(HOST, USER, PASS, DATABASE);
$email = strip_tags($_POST['email']);
$query = 'INSERT INTO usuarios (userEmail) VALUES (?)';
$stmt = mysqli_prepare($conectar, $query);
mysqli_stmt_bind_param($stmt, 's', $email);
mysqli_stmt_execute($stmt); //execute query
$userID = mysqli_insert_id($conectar);
//assign a role to the newly created user
$query = "INSERT INTO rolesUsuarios (userID, nombreRol) VALUES (?, 'registered')";
$stmt = mysqli_prepare($conectar, $query);
mysqli_stmt_bind_param($stmt, 's', $userID);
mysqli_stmt_execute($stmt); //execute query
var_dump($userID);
tell me, what did you will get in the end?
I am sorry to bother you with such a newbie question, and thank you for taking the time to go over it and answer it.
function dbaddusr($username, $email, $password){
try{
$conn = new PDO(CONNECTDATA);
$stmt = $conn->prepare("INSERT INTO 'users' ('username', 'email', 'password') VALUES (:username, :email, :password)");
$pass = crypt($password);
$result = $stmt->execute(array("username" => $username, "email" => $email, "password" => $pass));
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
return false;
}
}
Problem is, $result is always false. (I discovered this by some simple var_dump statements inside the try block.
I am very new to this and your help on fixing it is highly appreciated.
Don't quote the column names, if you want, use the backticks `
INSERT INTO users (username, email, password) VALUES (:username, :email, :password)
Change quotes to backticks for table & column name in your query,
$stmt = $conn->prepare("INSERT INTO `users` (`username`, `email`, `password`) VALUES
(:username, :email, :password)");
You are passing $pass in your array and your function accepts $password
Check your error messages to get specific details and you will find the problem.
A non-bloated version with all useless and wrong code cleaned.
function dbaddusr($username, $email, $password){
global $conn;
$sql = "INSERT INTO users (username, email, password) VALUES (?,?,?)";
$stmt = $conn->prepare($sql);
$pass = crypt($password);
$stmt->execute(array($username, $email, $pass));
}
You have to connect ONCE per application, and then use that single connection all the way.
I just to need make sure I've got the PDO prepare statements correctly, will the following code be secured by SQL Injection?
$data['username'] = $username;
$data['password'] = $password;
$data['salt'] = $this->generate_salt();
$data['email'] = $email;
$sth = $this->db->prepare("INSERT INTO `user` (username, password, salt, email, created) VALUES (:username, :password, :salt, :email, NOW())");
$sth->execute($data);
Yes, your code is safe. It can be shortened however:
$data = array( $username, $password, $this->generate_salt(), $email );
// If you don't want to do anything with the returned value:
$this->db->prepare("
INSERT INTO `user` (username, password, salt, email, created)
VALUES (?, ?, ?, ?, NOW())
")->execute($data);
You could start with an empty array for your $data like
// start with an fresh array for data
$data = array();
// imagine your code here
Your code looks good so far.
EDIT: I missed your NOW() call. Imho you should add it with a bind variable as well, like
// bind date
$data['created'] = date("Y-m-d H:i:s");
// updated prepare statement
$sth = $this->db->prepare("INSERT INTO `user` (username, password, salt, email, created) VALUES (:username, :password, :salt, :email, :created)");