PHP PDO transaction rollBack doesn't work - php

How is everything
Please can anyone help me in this
I'm trying to use PHP PDO transaction and there is a problem that I face and I can't deal with it.
rollBack function doesn't work when It catch an exception
Here is the connection code
$host = 'localhost';
$user = 'root';
$pass = '';
$error = '';
$dbname = 'tameras_finance';
// Set DSN
$dsn = 'mysql:host=' . $host . '; dbname=' . $dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try {
$dbh = new PDO($dsn, $user, $pass);
$dbh->exec("set names utf8");
}
//Catch any errors
catch (PDOException $e) {
echo $error = $e->getMessage();
}
and here the code
try{
$dbh->beginTransaction();
$dbh->query('SET #newDebit = (SELECT max(`debtor_id`) + 1 AS maxDebit FROM `vocher`)');
for($x = 0; $x < count($debits); $x++){
$dbh->query('UPDATE `vocher` SET `debtor_id` = #newDebit, `status_id` = "4" WHERE `id` = '.$debits[$x]);
}
for($x = 0; $x < count($others); $x++){
$columns = '`acc_id`, `value`, `date`, `desc`, `reject`, `vo_type_id`, `user`, `debtor_id`';
$vals = "'".$accs[$x]."','".$values[$x]."','".$dates[$x]."','".$descs[$x]."','1','1','".$user."', #newDebit";
if($others[$x] == 'e'){
$columns .= ', `cheque_no`, `available_date`, `issue_date`, `bank_id`';
$vals .= ", '".$sns[$x]."', '".$availdates[$x]."', '".$issueDates[$x]."', '".$banks[$x]."'";
}
$dbh->query("INSERT INTO creditor (".$columns.") VALUES (".$vals.")");
if($lists[$x] != 'e'){
$lastId = $dbh->lastInsertId();
$q = 'INSERT INTO `creditor_cc` (`creditor`, `cc`) VALUES ';
for($y = 0; $y < count($lists[$x]); $y++){
$dif = count($lists[$x]) - $y;
$q .= '(';
$q .= '"' . $lastId . '",';
$q .= '"'.$lists[$x][$y].'"';
$q .= ')';
if($dif > 1){
$q .= ',';
}
}
$dbh->query($q);
}
}
$dbh->commit();
} catch(PDOException $e) {
echo $error = $e->getMessage();
$dbh->rollBack();
}
This code doesn't rollback
Please note that:
$sns, $others, $accs, $values, $dates, $descs, $availdates,
$issueDates and $banks are arrays with the same size
Also $lists is a two dimension array with the same size
please help me with this why this code doesn't rollBack

Transactions are not supported on MySQL's default table type MyISAM. You need to make sure you're using InnoDB tables.
Also check to make sure the exception that's being thrown is PDOException or it'll fall through the try/catch and not hit your rollback.

I would say it shoud be done this way:
$pdo = new \PDO(/*...*/);
$pdo->beginTransaction();
try {
//...
} catch(\Exception $e) {
$pdo->rollBack();
throw $e;
}
$pdo->commit();

Related

Transactions in MySql not working via PDO first correct query performed [duplicate]

How is everything
Please can anyone help me in this
I'm trying to use PHP PDO transaction and there is a problem that I face and I can't deal with it.
rollBack function doesn't work when It catch an exception
Here is the connection code
$host = 'localhost';
$user = 'root';
$pass = '';
$error = '';
$dbname = 'tameras_finance';
// Set DSN
$dsn = 'mysql:host=' . $host . '; dbname=' . $dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try {
$dbh = new PDO($dsn, $user, $pass);
$dbh->exec("set names utf8");
}
//Catch any errors
catch (PDOException $e) {
echo $error = $e->getMessage();
}
and here the code
try{
$dbh->beginTransaction();
$dbh->query('SET #newDebit = (SELECT max(`debtor_id`) + 1 AS maxDebit FROM `vocher`)');
for($x = 0; $x < count($debits); $x++){
$dbh->query('UPDATE `vocher` SET `debtor_id` = #newDebit, `status_id` = "4" WHERE `id` = '.$debits[$x]);
}
for($x = 0; $x < count($others); $x++){
$columns = '`acc_id`, `value`, `date`, `desc`, `reject`, `vo_type_id`, `user`, `debtor_id`';
$vals = "'".$accs[$x]."','".$values[$x]."','".$dates[$x]."','".$descs[$x]."','1','1','".$user."', #newDebit";
if($others[$x] == 'e'){
$columns .= ', `cheque_no`, `available_date`, `issue_date`, `bank_id`';
$vals .= ", '".$sns[$x]."', '".$availdates[$x]."', '".$issueDates[$x]."', '".$banks[$x]."'";
}
$dbh->query("INSERT INTO creditor (".$columns.") VALUES (".$vals.")");
if($lists[$x] != 'e'){
$lastId = $dbh->lastInsertId();
$q = 'INSERT INTO `creditor_cc` (`creditor`, `cc`) VALUES ';
for($y = 0; $y < count($lists[$x]); $y++){
$dif = count($lists[$x]) - $y;
$q .= '(';
$q .= '"' . $lastId . '",';
$q .= '"'.$lists[$x][$y].'"';
$q .= ')';
if($dif > 1){
$q .= ',';
}
}
$dbh->query($q);
}
}
$dbh->commit();
} catch(PDOException $e) {
echo $error = $e->getMessage();
$dbh->rollBack();
}
This code doesn't rollback
Please note that:
$sns, $others, $accs, $values, $dates, $descs, $availdates,
$issueDates and $banks are arrays with the same size
Also $lists is a two dimension array with the same size
please help me with this why this code doesn't rollBack
Transactions are not supported on MySQL's default table type MyISAM. You need to make sure you're using InnoDB tables.
Also check to make sure the exception that's being thrown is PDOException or it'll fall through the try/catch and not hit your rollback.
I would say it shoud be done this way:
$pdo = new \PDO(/*...*/);
$pdo->beginTransaction();
try {
//...
} catch(\Exception $e) {
$pdo->rollBack();
throw $e;
}
$pdo->commit();

SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens COUNT IS CORRECT

I have been puzzling over this and trying to troubleshoot for hours. I have read maybe 30 questions on StackOverflow on this same error. None seem to pertain.
Field names and values are pulled from a long array. Previously, this was a MySQL query, that has worked well for the past 5 years, so nothing wrong with that array. As you can see, in troubleshooting, I added the variables $FCount, $VCount, and $PCount; to assure counts were the same, even though that's rather silly, as they are going to count as it goes through the loop, regardless. As a double-check, you can see in my exception code that I added the counts and strings as a second assurance, and counted them several times. I even exempted fields with blank values.
I am fairly new to PDO, and have no idea what is wrong here.
<?php
$DSN = "mysql:host=$HOST;dbname=$DBName;charset=utf8";
$Options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false,);
try{$pdo = new PDO($DSN, $USER, $PASSWORD, $Options);}
catch (PDOException $e)
{
$LogData = "\n".date('Y-m-d H:i').' '.$_SESSION[PageName].' '.$e->getMessage().' '.(int)$e->getCode();
error_log($LogData, 3, "error.log");
exit('<h2 style="width:90%; border:2px solid #FF0000; padding:15px;">Server Connect Error! [1]</h2>');
}
$FCount = 0;
$VCount = 0;
$PCount = 0;
foreach($RateVars as $key => $value)
{
if(!empty($value))
{
$FieldString .= trim($key) . ','; $FCount++;
$VarString .= '"' . addslashes(trim($value)) . '",'; $VCount++;
$PrepString .= '?, '; $PCount++;
}
}
$FieldString .= 'Server';
$VarString .= '"'.$Node.'"';
$PrepString .= '?';
$sql = 'INSERT INTO Archive ('.$FieldString.') VALUES ('.$PrepString.')';
$stmt = $pdo->prepare($sql);
try {$stmt->execute(array($VarString));}
catch (PDOException $e)
{
$ErrorMsg = "DataBase Error in Save to Archive"; $Status=1;
$LogData = "\n".date('Y-m-d H:i').' '.$_SESSION[PageName].' '.$ErrorMsg.' '.$e->getMessage().' '.(int)$e->getCode();
$LogData .= "\n".'F: '.$FCount.' V: '.$VCount.' P: '.$PCount;
$LogData .= "\n".'F: '.$FieldString."\n".' V: '.$VarString."\n".' P: '.$PrepString."\n".$sql;
error_log($LogData, 3, "error.log");
}
?>
Added note
Short example (there are 72 variables here) from my error log where I print out $sql:
INSERT INTO RateArchive (EstType,hszip,hczip,wswxds,etc...) VALUES ("W","58102","58652","000050000000000000","0500000000000000",etc.)
In answer to a comment below, the value of $Node is "DEV" and that is exactly how it comes out at the end of the value string.
Each parameter needs to be a separate element in the array passed to $stmt->execute(), it shouldn't be a single comma-separated string.
<?php
$DSN = "mysql:host=$HOST;dbname=$DBName;charset=utf8";
$Options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false,);
try{$pdo = new PDO($DSN, $USER, $PASSWORD, $Options);}
catch (PDOException $e)
{
$LogData = "\n".date('Y-m-d H:i').' '.$_SESSION[PageName].' '.$e->getMessage().' '.(int)$e->getCode();
error_log($LogData, 3, "error.log");
exit('<h2 style="width:90%; border:2px solid #FF0000; padding:15px;">Server Connect Error! [1]</h2>');
}
$FCount = 0;
$VCount = 0;
$PCount = 0;
$PrepString = str_repeat("?, ", count($RateVars));
$FieldString = implode(',', array_keys($RateVars));
$PrepString .= '?';
$FieldString .= ', Server';
$ValArray = array_values($RateVars);
$ValArray[] = $Node;
$sql = 'INSERT INTO Archive ('.$FieldString.') VALUES ('.$PrepString.')';
$stmt = $pdo->prepare($sql);
try {
$stmt->execute($ValArray);
} catch (PDOException $e)
{
$ErrorMsg = "DataBase Error in Save to Archive"; $Status=1;
$LogData = "\n".date('Y-m-d H:i').' '.$_SESSION[PageName].' '.$ErrorMsg.' '.$e->getMessage().' '.(int)$e->getCode();
$LogData .= "\n".'F: '.$FCount.' V: '.$VCount.' P: '.$PCount;
$LogData .= "\n".'F: '.$FieldString."\n".' V: '.implode(',', $ValArray)."\n".' P: '.$PrepString."\n".$sql;
error_log($LogData, 3, "error.log");
}
?>

php/pdo insert into database mssql with arrays

I need some help
Is there a way to make this in PDO? https://stackoverflow.com/a/1899508/6208408
Yes I know I could change to mysql but I use a mssql server and can't use mysql. I tried some things but I'm not as good with PDO as mysql... It's hard to find some good examples of inserting array's into database with PDO. So quickly said I have a PDO based code connected to a mssql webserver.
best regards joep
I tried this before:
//id
$com_id = $_POST['com_id'];
//array
$mon_barcode = $_POST['mon_barcode'];
$mon_merk = $_POST['mon_merk'];
$mon_type = $_POST['mon_type'];
$mon_inch = $_POST['mon_inch'];
$mon_a_date = $_POST['mon_a_date'];
$mon_a_prijs = $_POST['mon_a_prijs'];
$data = array_merge($mon_barcode, $mon_merk, $mon_type, $mon_inch, $mon_a_date, $mon_a_prijs);
try{
$sql = "INSERT INTO IA_Monitor (Com_ID, Barcode, Merk, Type, Inch, Aanschaf_dat, Aanschaf_waarde) VALUES (?,?,?,?,?,?,?)";
$insertData = array();
foreach($_POST['mon_barcode'] as $i => $barcode)
{
$insertData[] = $barcode;
}
if (!empty($insertData))
{
implode(', ', $insertData);
$stmt = $conn->prepare($sql);
$stmt->execute($insertData);
}
}catch(PDOException $e){
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
The code below should fix your problems.
$db_username='';
$db_password='';
$conn = new \PDO("sqlsrv:Server=localhost,1521;Database=testdb", $db_username, $db_password,[]);
//above added per #YourCommonSense's request to provide a complete example to a code fragment
if (isset($_POST['com_id'])) { //was com_id posted?
//id
$com_id = $_POST['com_id'];
//array
$mon_barcode = $_POST['mon_barcode'];
$mon_merk = $_POST['mon_merk'];
$mon_type = $_POST['mon_type'];
$mon_inch = $_POST['mon_inch'];
$mon_a_date = $_POST['mon_a_date'];
$mon_a_prijs = $_POST['mon_a_prijs'];
$sql = "INSERT INTO IA_Monitor (Com_ID, Barcode, Merk, Type, Inch, Aanschaf_dat, Aanschaf_waarde) VALUES (?,?,?,?,?,?,?)";
try {
$stmt = $conn->prepare($sql);
foreach ($mon_barcode as $i => $barcode) {
$stmt->execute([$com_id, $barcode, $mon_merk[$i], $mon_type[$i], $mon_inch[$i], $mon_a_date[$i], $mon_a_prijs[$i]]);
}
} catch (\PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
}
$conn = null;

PHP MySQL PDO SQLSTATE[HY000]: General error

Please help fix "SQLSTATE[HY000]: General error:" in the following PHP script. Also, refer to the MySQL script in case.
<?php
# MySQL
$host = 'localhost';
$username = 'root';
$password = '';
$dbname = 'procdb';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected to MySQL Server successfully." . "\n";
$sql = "CALL prepend('abcdefg', #inOutParam);";
$stmt = $pdo->query($sql);
do {
$rows = $stmt->fetchAll(PDO::FETCH_NUM);
if ($rows) {
foreach($rows as $row) {
print($row[0] . "\n");
}
}
} while ($stmt->nextRowset());
} catch (PDOException $e) {
#die("Could not connect to the database $dbname :" . $e->getMessage());
$error = $e->getMessage();
echo $error . "\n";
} catch (Exception $e) {
$error = $e->getMessage();
echo $error . "\n";
} finally {
$pdo = null;
echo "Connection closed." . "\n";
}
?>
Here's the MySQL Script:
DROP DATABASE IF EXISTS procdb;
DELIMITER $$
CREATE DATABASE procdb;$$
DELIMITER ;
USE procdb;
DROP PROCEDURE IF EXISTS prepend;
DELIMITER $$
CREATE PROCEDURE prepend
(
IN inParam VARCHAR(255),
INOUT inOutParam INT
)
BEGIN
DECLARE z INT;
SET z = inOutParam + 1;
SET inOutParam = z;
SELECT inParam;
SELECT CONCAT('zyxw', inParam);
END;$$
DELIMITER ;
USE procdb;
CALL prepend('abcdefg', #inOutParam);
/*
# Output
// (FieldName1 and its value)
inParam
'abcdefg'
// (FieldName2 and its value)
CONCAT('zyxw', inParam)
'zyxwabcdefg'
*/
What is the cause of the error? Note that adding "$stmt->close();" or "$stmt->closeCursor();" did not help.
Please help.
Thanks
Try this, line
$rows = $stmt->fetchAll(PDO::FETCH_NUM);
Outside While loop
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected to MySQL Server successfully." . "\n";
$sql = "CALL prepend('abcdefg', #inOutParam);";
$stmt = $pdo->query($sql);
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($rows as $row) {
foreach ($row as $col) {
print $col . "\n";
}
}
$stmt->nextRowset();
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($rows as $row) {
foreach ($row as $col) {
print $col . "\n";
}
}
} catch (PDOException $e) {
#die("Could not connect to the database $dbname :" . $e->getMessage());
$error = $e->getMessage();
echo $error . "\n";
} catch (Exception $e) {
$error = $e->getMessage();
echo $error . "\n";
} finally {
$pdo = null;
echo "Connection closed." . "\n";
}

PDO Update Help executing pdo update

The function is pretty straightforward:
The variables: $table is the table which the update is taking place
and $fields are the fields in the table,
and $values are generated from a post and put into the $values array
and $where is the value of the id of the index field of the table
and $indxfldnm is the index field name
function SQLUpdate($table,$fields,$values,$where,$indxfldnm) {
//Connect to DB
$dbaddr = DB_HOST;
$dbusr = DB_USER;
$dbpwd = DB_PASSWORD;
$dbname = DB_DATABASE;
$db = new PDO('mysql:host='.$dbaddr .';dbname='.$dbname.';charset=UTF8', $dbusr, $dbpwd);
//build the fields
$buildFields = '';
if (is_array($fields)) {
//loop through all the fields
foreach($fields as $key => $field) :
if ($key == 0) {
//first item
$buildFields .= $field;
} else {
//every other item follows with a ","
$buildFields .= ', '.$field;
}
endforeach;
} else {
//we are only inserting one field
$buildFields .= $fields;
}
//build the values
$buildValues = '';
if (is_array($values)) {
//loop through all the values
foreach($values as $key => $value) :
if ($key == 0) {
//first item
$buildValues .= '?';
} else {
//every other item follows with a ","
$buildValues .= ', ?';
}
endforeach;
} else {
//we are only updating one field
$buildValues .= ':value';
}
$sqlqry = 'UPDATE '.$table.' SET ('.$buildFields.' = '.$buildValues.') WHERE `'.$indxfldnm.'` = \''.$where.'\');';
$prepareUpdate = $db->prepare($sqlqry);
//execute the update for one or many values
if (is_array($values)) {
$prepareUpdate->execute($values);
} else {
$prepareUpdate->execute(array(':value' => $values));
}
//record and print any DB error that may be given
$error = $prepareUpdate->errorInfo();
if ($error[1]) print_r($error);
echo $sqlqry;
return $sqlqry;
}
So far so good
However its not working
there is something wrong with transferring the values into the fields in a proper update statement
but I'm not so good with pdo and setting it up
a little help to fix the code to bind the parameters to the values in an update would
be greatly appreciated
Thank you
Try getting this in your function
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
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);
$sql = "UPDATE MyGuests SET lastname='Doe' WHERE id=2";
// 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;
?>
Changed Code to a different build:
This eliminated the multiple-value problem
function SQLUpdate($table,$fields,$values,$where,$indxfldnm) {
$dbdata = array();
$i=0;
foreach ($fields as $fld_nm)
{
if ($i > 0) {
$dbdata[$fld_nm] = $values[$i]; }
$i++;
} //end foreach
$buildData = '';
foreach ($dbdata as $key => $val) {
if (empty($val)) {$buildData .= '`'.$key.'` = \'NULL\', ';} else {
$buildData .= '`'.$key.'` = \''.$val.'\', ';}
}
$buildData = substr($buildData,0,-2);
$dbaddr = DB_HOST;
$dbusr = DB_USER;
$dbpwd = DB_PASSWORD;
$dbname = DB_DATABASE;
$prepareUpdate ='';
try {
$db = new PDO('mysql:host='.$dbaddr .';dbname='.$dbname.';charset=UTF8', $dbusr, $dbpwd);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec("SET CHARACTER SET utf8");
$sqlqry = 'UPDATE '.$table.' SET '.$buildData.' WHERE `'.$indxfldnm.'` = \''.$where.'\';';
$prepareUpdate = $db->exec($sqlqry);
//execute the update for one or many values
}
catch(PDOException $e)
{
$e->getMessage();
print_r($e);
}
return $sqlqry;
}
//END: SQLUpdate

Categories