Transactions with PDO and prep. statements - php

I need to insert to two tables and I tried transactions. It works well:
$nom = "Nrc";
$contrasenya = "somePassword";
$conn->beginTransaction();
$conn->exec("INSERT INTO usuari (nom, contrasenya)
VALUES ('$nom', '$contrasenya')");
$conn->exec("INSERT INTO well (puntuacio, text)
VALUES ('9', 'some text2')");
$conn->commit();
echo "New records created successfully";
Now I want to introduce prep. statements for security. I am not sure how to do that. This is what I tried. It gives me no error, but it does not insert in any table either:
$nom = "Nrc";
$contrasenya = "somePassword";
$conn->beginTransaction();
$stmt = $conn->prepare("INSERT INTO usuari (nom, contrasenya)
VALUES (:nom, :contrasenya)");
$stmt = $conn->prepare("INSERT INTO well (puntuacio, text)
VALUES ('9', 'some text2')");
$stmt->bindParam(':nom', $nom);
$stmt->bindParam(':contrasenya', $contrasenya);
$conn->commit();
echo "New records created successfully";

There are several issues with your code:
You never execute the statement.
You overwrite your statement ($stmt) with the statement using the values directly. So you don't use the correct prepared statement.
You can use the following code to INSERT the values to the tables:
//start the transaction.
$conn->beginTransaction();
//the variables of the first statement.
$nom = 'Nrc';
$contrasenya = 'somePassword';
//prepare the first statement, bind the values and execute.
$stmt = $conn->prepare("INSERT INTO usuari (nom, contrasenya) VALUES (:nom, :contrasenya)");
$stmt->bindParam(':nom', $nom);
$stmt->bindParam(':contrasenya', $contrasenya); //TODO - use hashing here!
//... or solution without variable.
//$stmt->bindValue(':nom', 'Nrc');
//$stmt->bindValue(':contrasenya', 'somePassword');
$stmt->execute();
//the variables of the second statement.
$puntuacio = '9';
$text = 'some text2';
//prepare the second statement, bind the values and execute.
$stmt = $conn->prepare("INSERT INTO well (puntuacio, text) VALUES (:puntuacio, :text)");
$stmt->bindParam(':puntuacio', $puntuacio);
$stmt->bindParam(':text', $text);
//... or solution without variable.
//$stmt->bindValue(':puntuacio', '9');
//$stmt->bindValue(':text', 'some text2');
$stmt->execute();
//commit all changes of the transaction.
$conn->commit();
Note: As already others mentioned, you should also hash your passwords.

From php.net:
Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.

For password insertion you should use password() function shiped with PHP.
You shouldn't insert direct data directly in prepare statement, as you did for the first one
$stmt = $conn->prepare("INSERT INTO well (puntuacio, text)
VALUES (:number, :some_text)");
$stmt->bindParam(':number', $num);
$stmt->bindParam(':some_text', $text);
You should execute(); your prepared statement in order to execute your query insertion.
Plus as said previously you overwrite your $stmt variable before you can execute your query.

Related

Inserting into 2 tables PHP with subquery, last insert id, and prepared statement

So, I have problem with inserting data into 2 tables directly using subquery and last insert id.
i have following codes
if (isset($_POST['recipient']))
$recipient = sanitize($_POST['recipient']);
if (isset($_POST['message']))
$message = sanitize($_POST['message']);
$sql = "INSERT INTO message (senderID, message)
VALUES (?,?)";
if ($stmt = mysqli_prepare($connection, $sql)) {
mysqli_stmt_bind_param($stmt, "is", $userID, $message);
mysqli_stmt_execute($stmt);
$newID = mysqli_insert_id($connection);
$sql2 = "INSERT INTO message_recipient (messageID, recipientID)
SELECT ?, userID
from user
where username = $recipient";
if ($stmt2 = mysqli_prepare($connection, $sql)) {
mysqli_stmt_bind_param($stmt2, "ii", $newID, $recipient);
mysqli_stmt_execute($stmt2);
mysqli_stmt_close($stmt2);
}
}
for the $stmt2 ,it works well in phpmyadmin, but without the prepared statement. The first query works well, it can add data, but can't the second. Also, i dont know why the first query will insert 2 data, with first data correct and second false.
Is the way i get last insert id wrong, or my second query is false?
Any help given really appreciated. thank you so much

prepared statement not executing but msqli_stmt_execute returning true

I have an insert query below and am checking if the insert was successful using: mysqli_stmt_execute. The query is not executing as the values are not being entered into my db. However, I am getting into the if condition. I cannot understand this. I have wrapped the stmt_prepare in an if condition previously and that also was returning true tht it was preparing successfully. I did the same with the bind statement and now I have it on the final execute statement. All return true but the query is not executing. The structure of the table is correct. I even preformed an insert in phpmyadmin and pasted the generated query into my AddToken variable.
$con = 'my login credentials'
$stmt = mysqli_stmt_init($con);
$AddToken = "INSERT INTO `auth` VALUES ('',?, ?)";
mysqli_stmt_prepare($stmt, $AddToken);
mysqli_stmt_bind_param($stmt, "si", $Token, $ID);
if (mysqli_stmt_execute($stmt)){
$message2 = "here";
// worked
}
else{
//didn't work
$message2 = "here 2";
}
echo $message2;
EDIT I have no idea what the problem was but I deleted my auth table and recreated it and it worked?
You need not have empty strings in your VALUES()in the insert query, since you are inserting only two values
May be better to specify the column names if you know
$AddToken = "INSERT INTO `auth` (column1, column2) VALUES (?, ?)";

prepared INSERT statement to get insert_id to use in a second prepared INSERT statement

Im trying to create my own register form but im having issues with prepared statements.
the idea is to create a prepared statement to insert info into the user table, then from that get the insert_id from the generated content to use in another insert statement
here is a version of my register script
<?php
$returnedId = '';
include "includes/dbconnect.php";
$stmt = $db->prepare("INSERT INTO `users`(`Username`, `Email`, `Password`) VALUES (?, ?, ?)");
$stmt->bind_param('sss', $_POST['username'], $_POST['email'], $_POST['password']);
$stmt->execute();
$returnedId = $stmt->insert_id;
$stmt->close();
echo $returnedId;
$allergystmt = $db->prepare("INSERT INTO 'user_allergy' ('user_id', 'allergy_id') VALUES (?, ?)");
$allergystmt->bind_param('ss', $returnedId, $_POST['check_list']);
$allergystmt->execute();
$allergystmt->close();
header('Location: index.php');
?>
the first prepared statement runs correctly and inserts information into the table, after that the $returnId variable is successfully echoed. next in the script is my second prepared statement, when it tries to run im getting the error that says:
Fatal error: Call to a member function bind_param() on a non-object in D:\filepath\register.php on line 17
it seems that my variable isnt being carried into the second prepared statement.
Your second query has syntax errors and failed to prepare. Since you have no error handling for database failures like this, your later code just blunders onwards:
$allergystmt = $db->prepare("INSERT INTO 'user_allergy' ('user_id', 'allergy_id') VALUES (?, ?)");
^--- ^--^--- ^-- etc...
You cannot use ' quotes on table and field names. ' indicate strings. None of those field/table names are reserved words, so there is NO need to quote them at at all:
$allergystmt = $db->prepare("INSERT INTO user_allergy (user_id, allergy_id) VALUES (?, ?)");
if (!$allergystmt) { die($dbh->errorInfo()); }
Note the addition of the errorInfo() output. Never assume a DB operation was successful. Always assume failure, and treat success as a pleasant surprise.

inserting data from a form into your mysql database using php

i used this code
<?php
$conn = new PDO("mysql:host=localhost;dbname=CU4726629",'CU4726629','CU4726629');
$sql="INSERT INTO review (username, movie_name, ratings) VALUES ("$_POST['username']","$_POST['moviename']","$_POST['ratings']")";
header('Location: reviews.php');
?>
but it keeps giving me this error
Parse error: syntax error, unexpected T_VARIABLE in
/home/4726629/public_html/check_login.php on line 5
Take this for an example:
<?php
// insert some data using a prepared statement
$stmt = $dbh->prepare("insert into test (name, value) values (:name, :value)");
// bind php variables to the named placeholders in the query
// they are both strings that will not be more than 64 chars long
$stmt->bindParam(':name', $name, PDO_PARAM_STR, 64);
$stmt->bindParam(':value', $value, PDO_PARAM_STR, 64);
// insert a record
$name = 'Foo';
$value = 'Bar';
$stmt->execute();
// and another
$name = 'Fu';
$value = 'Ba';
$stmt->execute();
// more if you like, but we're done
$stmt = null;
?>
You just wrote a string in your above code:
$sql="INSERT INTO review (username, movie_name, ratings) VALUES ("$_POST['username']","$_POST['moviename']","$_POST['ratings']")";
Above answers are correct, you will need to concat the strings to form a valid sql query. you can echo your $sql variable to check what is to be executed and if is valid sql query or not. you might want to look in to escaping variables you will be using in your sql queries else your app will be vulnerable to sql injections attacks.
look in to
http://php.net/manual/en/pdo.quote.php
http://www.php.net/manual/en/pdo.prepare.php
Also you will need to query you prepared sql statement.
look in to http://www.php.net/manual/en/pdo.query.php
A couple of errors:
1) you have to concat the strings!
like this:
$sql="INSERT INTO review (username, movie_name, ratings)
VALUES (".$_POST['username'].",".$_POST['moviename'].",".$_POST['ratings'].")";
2) you are not using the PDO at all:
after you create the "insert" string you must query the db itself, something like using
$conn->query($sql);
nb: it is pseudocode
3) the main problem is that this approach is wrong.
constructing the queries in this way lead to many security problems.
Eg: what if I put "moviename" as "; drop table review;" ??? It will destroy your db.
So my advice is to use prepared statement:
$sql="INSERT INTO review (username, movie_name, ratings)
VALUES (?,?,?)";
$q = $conn->prepare($sql);
$fill_array = array($_POST['username'], $_POST['moviename'], $_POST['ratings']);
$q->execute($fill_array);
You forgot dots:
$sql="INSERT INTO review (username, movie_name, ratings)
VALUES (".$_POST['username'].",".$_POST['moviename'].",".$_POST['ratings'].")";
and fot the future for now your variables are not escaped so code is not secure
String in a SQL-Statment need ', only integer or float don't need this.
$sql="INSERT INTO review (username, movie_name, ratings) VALUES ('".$_POST['username']."','".$_POST['moviename']."','".$_POST['ratings']."')";

Using one ? to contain several variables in PHP MySQLi prepared INSERT statement

Trying to get to grips with prepared statements for an INSERT query. This is supposed to add a new user to the database:
$statement = $mysqli->prepare("INSERT INTO users (email,passwordhash) VALUES (?)");
$statement->bind_param('s', "'$email','$passwordhash'");
$statement->execute();
Is it correct to use a single ? and fill it with two values in that way?
The way mysqli doing that you need to bind all the variables separately
$statement = $mysqli->prepare("INSERT INTO users (email,passwordhash) VALUES (?,?)");
$statement->bind_param('ss', $email,$passwordhash);
$statement->execute();
But if you want it your way (say, you have an array ready and want to insert it using one placeholder) you need a helper class which will translate a custom placeholder into correct SQL statement:
$data = array('email'=>$email, 'passwordhash'=>$passwordhash);
$db->query("INSERT INTO users SET ?u");
and it will be shorter than raw mysqli yet will do much more - error handling, profiling and such.
Also keep in mind that when you will have a variable number of fields to insert, mysqli will turned to be a nightmare.
In prepared statements, each ? is used to replace one value.
When executed, your query will be:
INSERT INTO users (email,passwordhash) VALUES ("'email','password'")
That's not what you want. You need to use 2 ?s, one for each value.
$statement = $mysqli->prepare("INSERT INTO users (email,passwordhash) VALUES (?,?)");
// Pass each variable as a separate parameter
$statement->bind_param('ss', $email, $passwordhash);
$statement->execute();
Should be like this.
$statement = $mysqli->prepare("INSERT INTO users (email,passwordhash) VALUES (?,?)");
$statement->bind_param('ss', $email,$passwordhash);
$statement->execute();

Categories