PHP PDO prepare transaction statement (Two inserts) - php

I have tried to insert two insert intos through a transaction statement but it did not work. The console is giving me database errors. I have checked the documentation http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers and it is obvious I am missing something.
The goal is simply insert into two different tables different information. I tried the following:
// create record
function create(){
try {
$stmt->beginTransaction();
$query = "INSERT INTO " . $this->table_name . "
SET user_id = ?, ";
// prepare query statement
$stmt = $this->conn->prepare($query);
// bind values to be inserted
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
$query2 = "INSERT INTO legalcases_report
SET user_id = ?, ";
// prepare query statement 2
$stmt = $this->conn->prepare($query2);
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
$stmt->commit();
return true;
} catch (Exception) {
$stmt->rollBack();
return false;
}
}

There are lots of problems in this code, I hope I can catch them all
// create record
function create(){
try {
// transaction work on a connection and not a statement
//$stmt->beginTransaction();
$this->conn->beginTransaction();
// Incorrect syntax for an INSERT command
// Error - Trailing comma in sytax
$query = "INSERT INTO " . $this->table_name . "
SET user_id = ?, ";
// prepare query statement
$stmt = $this->conn->prepare($query);
// bind values to be inserted
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
// Incorrect syntax for an INSERT command
// Error - Trailing comma in sytax
$query2 = "INSERT INTO legalcases_report
SET user_id = ?, ";
// prepare query statement 2
$stmt = $this->conn->prepare($query2);
$stmt->bindParam(1, $this->user_id);
$stmt->execute();
// commit also works on a connection object
//$stmt->commit();
$this->conn->commit();
return true;
// PDO generates a PDOException so you should really catch that,
// it will fallback to the parent Exception object, BUT
// there may be times when you want to catch them seperately
// from the same try block, so use the correct one or both
} catch (PDOException $pex) {
$this->con->rollback();
$pex->getMessage();
exit; // because you have a serious problem
// or throw your own exception to the calling code
throw new Exception('Create user failed ' . $pex->getMessage());
}
}
Incorrect syntax for an INSERT command
The PHP PDO manual

I guess you should use PDO object, not PDOStatement:
try {
$this->conn->beginTransaction();
...
$this->conn->commit();

Related

How can I prevent SQL from being executed until POST values are not empty?

I have the following PHP script that executes an sql update query, how can I prevent it from being executed until the two POST values are not empty?
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$delivery_time = addslashes($_POST['delivery_time']);
$customer = addslashes($_POST['customer']);
$sql = "UPDATE Equipment SET time = '$time', customer = '$customer' WHERE status ='Broken' ";
// Prepare statement
$stmt = $conn->prepare($sql);
// execute the query
$stmt->execute();
// echo a message to say the UPDATE succeeded
echo $stmt->rowCount() . " records UPDATED successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
Warning: You are wide open to SQL Injections and should really use parameterized prepared statements instead of manually building your queries. They are provided by PDO or by MySQLi. Never trust any kind of input, especially that which comes from the client side. Even when your queries are executed only by trusted users, you are still in risk of corrupting your data.
To avoid sending the query until $_POST variables are supplied check for their existence with if statement and isset.
if (isset($_POST['delivery_time'], $_POST['customer'])) {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // switch off emulated prepares, but you should add charset=utf8mb4 in the contructor above too
$sql = "UPDATE Equipment SET `time` = ?, `customer` = ? WHERE `status` ='Broken' ";
// Prepare statement
$stmt = $conn->prepare($sql);
// execute the query
$stmt->execute([
$_POST['delivery_time'],
$_POST['customer']
]);
// echo a message to say the UPDATE succeeded
echo $stmt->rowCount() . " records UPDATED successfully";
}

Get the InsertId with Prepared Statements AND Stored Procedures?

I had some Prepared Statements working in PHP using mysqli. The requirements changed and now I'm supposed to move them to the DB, as Stored Procedures. This worked fine for most of the PSs, except for a couple that read the insertId for some further processing.
Ex:
$idAsdf = $stmtAsdf->insert_id;
where the PS performs an INSERT operation.
I've tried using an OUT parameter on the procedure which works fine on PHPMyAdmin, but can't connect it with the PHP server code outside the DB. I haven't found any example of this combination of elements being done. How can I get this insertId using both SPs and PSs?
Thanks
For PDO Prepared Statement you can use PDO::lastInsertId -http://php.net/manual/en/pdo.lastinsertid.php
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $dbh->prepare("INSERT INTO test (name, email) VALUES(?,?)");
try {
$dbh->beginTransaction();
$tmt->execute( array('user', 'user#example.com'));
print $dbh->lastInsertId();
$dbh->commit();
} catch(PDOExecption $e) {
$dbh->rollback();
print "Error!: " . $e->getMessage() . "</br>";
}
} catch( PDOExecption $e ) {
print "Error!: " . $e->getMessage() . "</br>";
}
?>
Just remember when using transaction return lastInsertId or store lastInsertId before commit.
For Stored Procedure - use LAST_INSERT_ID();
BEGIN
INSERT INTO test (name, email) VALUES ('value1', 'value2');
SET out_param = LAST_INSERT_ID();
END
EDIT 1 :
If you using MySQLi - then use mysqli_insert_id - http://php.net/manual/en/mysqli.insert-id.php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$stmt = mysqli->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "john#example.com";
$stmt->execute();
printf ("New Record has id %d.\n", $stmt->insert_id);
/* close connection */
$mysqli->close();
If facing problem with out_param, use select to return last insert id as result.
BEGIN
DECLARE last_id INT DEFAULT 0;
INSERT INTO test (name, email) VALUES ('value1', 'value2');
SET last_id = LAST_INSERT_ID();
SELECT last_id;
END
EDIT 2 :
If you are facing problem in retrieving Stored Procedure result set use following code -
if ($mysqli->multi_query($query)) {
do {
/* store first result set */
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
printf("%s\n", $row[0]);
}
$result->free();
}
/* print divider */
if ($mysqli->more_results()) {
printf("-----------------\n");
}
} while ($mysqli->next_result());
}
To access the out param use follwing code -
// execute the stored Procedure
// #uid - IN param, #userCount - OUT param
$result = $connect->query('call IsUserPresent(#uid, #userCount)');
// getting the value of the OUT parameter
$r = $connect->query('SELECT #userCount as userCount');
$row = $r->fetch_assoc();
$toRet = ($row['userCount'] != 0);
insert_id is a property of mysqli class, while you are trying to get it from a statement object.
inside SP you can set like this outParam = LAST_INSERT_ID();
LAST_INSERT_ID() returns the most recently generated ID is maintained in the server on a per-connection basis.

Delete function not working within a transaction pdo php mysql

I am having similar problems as this colleague: similar problem
I am surprised that a Delete function within a transaction with pdo does not behave properly. If I use the delete function alone in a pdo it works perfectly but when I combine the delete function with an update function in a transaction it stops working (only first query works). I have tried all the answer and tips from the old thread but nothing seems to work. Can someone help me here?
The code that I am working with:
function denyactionevent(){
try {
$$this->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
$$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->conn->beginTransaction();
// product update query
$query = "UPDATE
" . $this->table_name . "
SET
accepted = :accepted
WHERE
id = :id";
// prepare query statement
$stmt = $this->conn->prepare($query);
// bind variable values
$stmt->bindParam(':accepted', $this->accepted);
$stmt->bindParam(':id', $this->id);
// execute the query
$stmt->execute();
$query2 = "DELETE
FROM event_case
WHERE reference = :id
";
// prepare query statement
$stmt = $this->conn->prepare($query2);
// bind values
$stmt->bindParam(':id', $this->id);
// execute the query
$stmt->execute();
$this->conn->commit();
return true;
} catch (Exception $e) {
$stmt->rollBack();
return false;
}
}

Catchable fatal error: Object of class PDOStatement could not be converted to string, w

I know this has been asked before but can't find a answer to my specific instance of this error.
Catchable fatal error: Object of class PDOStatement could not be converted to string
Here is my code:
try
{
// create connection and set error attributes
$conn = new PDO("mysql:host=" . HOST . "; dbname=" . DATABASE, USER, PASS);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//define insert and query variables
$query = "SELECT * FROM cart WHERE user_id=? AND product_id=?;";
$insert = "INSERT INTO cart (user_id, product_id, qty, date)
VALUES ('$sessId', :i, :q, 'Now()');";
// execute a query to check if item all ready exist in cart
$r = $conn->prepare($query);
$r->execute(array(
session_id(),
$i
));
if ($r->rowCount() > 0) {
echo 'Item already exists in cart';
} else {
$q = $conn->prepare($insert);
$q->bindParam(':i', $i);
$q->bindParam(':q', $q);
$q->execute();
header('Location:../shopping_cart.php');
}
$r->closeCursor();
}
catch (PDOException $e)
{
echo $e->getMessage();
}
I cant find anything wrong with it, otherwise I just need to know what I need to do to get the values to convert, or should I look into another method.
Change the name of variable $q, you are changing type for nothing.
$q = $conn->prepare($insert);
$q->bindParam(':i', $i);
$q->bindParam(':q', $q); //binding a prepare statement itself?
Change to, and define the $qty with initial value of $q.
$q = $conn->prepare($insert);
$q->bindParam(':i', $i);
$q->bindParam(':q', $qty);
First you are testing if there is at least one record using
session_id()
If not then you are trying to insert with
$sessId
Assuming that they somehow have the same value...
I think you should insert with real prepared statement like:
$insert = "INSERT INTO cart (user_id, product_id, qty, date)
VALUES (:s, :i, :q, :n);";
...
...
...
$q = $conn->prepare($insert);
$q->bindParam(':s', $sessId);
$q->bindParam(':i', $i);
$q->bindParam(':q', $qty);
$q->bindParam(':n', Now());
$q->execute();
header('Location:../shopping_cart.php');

Calling method from a non-object?

$query = "INSERT INTO users (name, password) VALUES ('$myusername', '$mypassword')";
if (!($result = $mysqli->query($query)))
die("WHAT???? " . $mysqli->error . " EEEEEFFFFFFF.");
$count = $result->num_rows;
while ($row = $result->fetch_array()) {
if ($row[name] == $myusername) {
$mysqli->query("DELETE FROM users WHERE name='$myusername' AND password='$mypassword'");
$count = 5;
}
}
When I run this, it gives me an error:
Fatal error: Call to a member function fetch_array() on a non-object in /home/appstore/public_html/phpstoof/signedup.php on line 26
Where line 26 is where the while statement starts (while(x)). $mysqli ALREADY an instance of mysqli(). I don't see the how this is an error if the same code works on another file.
An INSERT statement has nothing to fetch.
As #mellamokb says, INSERT has nothing to fetch. Also you have used a mix of MySQL and MySQLi.
With MySQLi, the code should be like:
$mysqli = new mysqli($db_host, $db_username, $db_password, $db_database);
$str_sql = 'INSERT INTO users (name, password) VALUES (?, ?)';
// Create a prepared statement
$stmt = $mysqli->prepare($str_sql);
// Bind parameters for markers; same order and same count in prepared statement
$stmt->bind_param('ss', $myusername, $mypassword);
// Execute query
$stmt->execute();
// *************************************************************************
// If you're using a SELECT statement, each output field must be bound to
// a variable in the same order as in SELECT
// Bind result variables
$stmt->bind_result($_var1, $_var2, $_var3, ...);
// Fetch results and generate output as an associative array
while ($stmt->fetch())
{
// Handle $_var1, $_var2, $_var3, ...
}
// *************************************************************************
// Free stored result memory
$stmt->free_result();
// Close statement
$stmt->close();
// Close connection
$mysqli->close();

Categories