I have a loop that inserts data in two tables, in the first iteration of the loop the insert is succesfull, but in the second iteration the insert will fail.
I have written the script so that if any of the iterations fail, the entire transaction should be rollbacked. However, this doesn't work.
The first iteration (that succeeded) isn't rolled back...
<?php
include('model/dbcon.model.php');
$languages = array('project_nl', 'project_en');
DBCon::getCon()->beginTransaction();
$rollback = true;
foreach($languages as $language) {
$Q = DBCon::getCon()->prepare('INSERT INTO `'.$language.'`(`id`, `name`, `description`, `big_image`) VALUES (:id,:name,:description,:big_image)');
$Q->bindValue(':id', '1', PDO::PARAM_INT);
$Q->bindValue(':name', 'test', PDO::PARAM_INT);
$Q->bindValue(':description', 'test', PDO::PARAM_INT);
$Q->bindValue(':big_image', 'test', PDO::PARAM_INT);
try {
$Q->execute();
} catch (PDOException $e) {
$rollback = true;
}
}
if ($rollback) {
echo 'rollbacking...';
DBCon::getCon()->rollBack();
} else {
echo 'commiting...';
DBCon::getCon()->commit();
}
?>
Why isn't the entire transaction rolled back?
Thanks in advance.
Either auto-commit is enabled, or the connection is not persisting, or you're not using innodb.
This will work, which means DBCon::getCon() is not doing what you think it's doing.
<?php
include('model/dbcon.model.php');
$languages = array('project_nl', 'project_en');
$connection = DBCon::getCon();
$connection->beginTransaction();
$rollback = true;
foreach($languages as $language) {
$Q = $connection->prepare('INSERT INTO `'.$language.'`(`id`, `name`, `description`, `big_image`) VALUES (:id,:name,:description,:big_image)');
$Q->bindValue(':id', '1', PDO::PARAM_INT);
$Q->bindValue(':name', 'test', PDO::PARAM_INT);
$Q->bindValue(':description', 'test', PDO::PARAM_INT);
$Q->bindValue(':big_image', 'test', PDO::PARAM_INT);
try {
$Q->execute();
} catch (PDOException $e) {
$rollback = true;
}
}
if ($rollback) {
echo 'rollbacking...';
$connection->rollBack();
} else {
echo 'commiting...';
$connection->commit();
}
?>
Related
PHP PDO Statement inserting Null value to Db table
MY CODE:-
function pdate_product_desc_preview($fieldvalues, $company_digms1, $company_digms2, $company_digms3)
{
$query = "INSERT INTO eco_product_descTemp(`blockdigms1`, `blockdigms2`, `blockdigms3`) values(:company_digms1,:company_digms2,:company_digms3)";
try {
$stmt = $this->conn->prepare($query);
$stmt->bindValue(":company_digms1", $company_digms1);
echo $company_digms2;
$stmt->bindValue(":company_digms2", $company_digms2);
echo $company_digms3;
$stmt->bindValue(":company_digms3", $company_digms3);
$stmt->execute();
var_dump($stmt->errorInfo());
$productid = $this->conn->lastInsertId();
return $productid;
} catch (PDOException $e) {
$e->getMessage();
}
}
When i am executing, it only insert null value with auto increment id.
Thanks in advance.
function pdate_product_desc_preview($fieldvalues, $company_digms1, $company_digms2, $company_digms3)
{
$query = "INSERT INTO eco_product_descTemp (`blockdigms1`, `blockdigms2`, `blockdigms3`) values(:company_digms1,:company_digms2,:company_digms3)";
try {
$stmt = $this->conn->prepare($query);
$stmt->bindParam(":company_digms1", $company_digms1);
echo $company_digms2;
$stmt->bindParam(":company_digms2", $company_digms2);
echo $company_digms3;
$stmt->bindParam(":company_digms3", $company_digms3);
$stmt->execute();
var_dump($stmt->errorInfo());
$productid = $this->conn->lastInsertId();
return $productid;
} catch (PDOException $e) {
$e->getMessage();
}
}
Try this one.
Just replacing bindValue with bindParam
You can check prepared-statements.php here.
I've left $fieldvalues in but i dont see what it is doing..
Here's my take on it:
function pdate_product_desc_preview($fieldvalues, $company_digms1, $company_digms2, $company_digms3)
{
if (!empty($company_digms1) && !empty($company_digms2) && !empty($company_digms3))
{
$stmt = $this->conn->prepare("INSERT INTO `eco_product_descTemp` (`blockdigims1`, `blockdigims2`, `blockdigims3`) VALUES (?,?,?)");
$stmt->execute([$company_digms1, $company_digms2, $company_digms3]);
echo 'Inserted!';
} else {
echo 'make sure all fields have been filled in!';
}
}
So on the condition that if none of the fields are empty (NULL) then run the query. If one is empty (NULL) then run the make sure statement.
Code below adds data in db
$sth = $this->db->prepare('UPDATE `adwords_clients_google` set status = 2');
$sth->execute();
$sth = null;
$sth = $this->db->prepare('
INSERT INTO
`adwords_clients_google`
(`client_foreign_id`, `status`, `client_name`, `client_currency`)
VALUES
(:id, 1, :name, :currency)
ON DUPLICATE KEY UPDATE
`status` = VALUES(`status`),
`client_name` = VALUES(`client_name`),
`client_currency` = VALUES(`client_currency`)
');
$sth->bindParam(':id', $id);
$sth->bindParam(':name', $name);
$sth->bindParam(':currency', $currency);
foreach($accounts as $account) {
$id = $account->customerId;
$name = $account->name;
$currency = $account->currencyCode;
$sth->execute();
}
and I would like to add try here, something like
try {
if ($sth->execute()) {
helper::putToLog('ok queryCampaignArr, inserted rows: ' . $sth->rowCount());
} else {
helper::putToLog('not ok', true);
}
} catch (Exception $ex) {
helper::putToLog($sth->debugDumpParams(), true);
helper::putToLog("ERROR: ".$ex->getMessage(), true);
}
but i don't know should I add it for every row? How can I do that?
If you are using PDO for connecting DB then use PDOException class to handle the exception.
try {
if ($sth->execute()) {
helper::putToLog('ok queryCampaignArr, inserted rows: ' . $sth->rowCount());
} else {
helper::putToLog('not ok', true);
}
} catch (PDOException $ex) {
$Exception->getMessage(); // Error message
(int)$Exception->getCode(); // Error Code
}
i have several database checks with PDO before i insert some values on the DB and i don't know if one try/catch will catch all errors in the nested PDO or if i need one try/catch for every PDO. This is the code i got now:
try {
$db = connect_db();
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $foobar);
$status = $stm->execute();
if ($stm->rowCount() == 0) {
if ($def == 0) {
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $foobar);
$stm->bindParam(2, $foobar);
$stm->bindParam(3, $foobar);
$stm->bindParam(4, $foobar);
$status = $stm->execute();
if ($status) {
echo "<script>alert('foobar');window.location.assign('admin.php');</script>";
} else {
echo "<script>alert('foobar');window.location.assign('admin.php');</script>";
die();
}
} else {
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $nombre);
$status = $stm->execute();
if ($stm->rowCount() == 0) {
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $foobar);
$stm->bindParam(2, $foobar);
$stm->bindParam(3, $foobar);
$stm->bindParam(4, $user);
$status = $stm->execute();
if ($status) {
echo "<script>alert('foobar.');window.location.assign('admin.php');</script>";
} else {
echo "<script>alert('foobar.');window.location.assign('admin.php');</script>";
die();
}
}
}
} else {
echo "<script>alert('foobar.'); history.back();</script>";
die();
}
} catch (Exception $e) {
// Proccess error
$msg = $e->getMessage();
$timestamp = date("Y-m-d H:i:s");
$line = $e->getLine();
$code = $e->getCode();
handle_error($msg, $timestamp, $line, $code);
die("foobar");
}
PDO::ERRMODE_EXCEPTION
In addition to setting the error code, PDO will throw a PDOException and set its properties to reflect the error code and error information. This setting is also useful during debugging, as it will effectively "blow up" the script at the point of the error, very quickly pointing a finger at potential problem areas in your code (remember: transactions are automatically rolled back if the exception causes the script to terminate).
Exception mode is also useful because you can structure your error handling more clearly than with traditional PHP-style warnings, and with less code/nesting than by running in silent mode and explicitly checking the return value of each database call.
So, one is enough
i got two methods.one method is to insert data and the other one is to get the id of the inserted data. i tried several test but it doesn't give any return value.is it possible to pass a return value from another method?
public function insertRegistrantInfo($fname, $lname) {
$query = $this->db->prepare("INSERT INTO `registrants_info` (`first_name`, `last_name`) VALUES (?,?)");
$query->bindValue(1, $fname);
$query->bindValue(2, $lname);
try {
$row = $query->execute();
//$log = $this->getSessionID($email);
return $this->getSessionID($email);
#mail function can be added here
}catch(PDOException $e) {
die($e->getMessage());
}
}
public function getSessionID($email) {
try {
//global $bcrypt;
$query = $this->db->prepare("SELECT `id` FROM `registrants_info` WHERE `email` = ?");
$query->bindValue(1, $email);
$query->execute();
$data1 = $query->fetch();
$id = $data1['id'];
//echo $id;
return $id;
} catch(PDOException $e) {
die($e->getMessage());
}
}
and the returning page is here:
if($data = $admin->insertRegistrantInfo($fname, $lname) == true) {
session_regenerate_id(true);
$_SESSION['id'] = $data;
//print_r($_SESSION);
header('location: registry.php');
exit();
}
Use the lastInsertID() method on your query object rather than a second query
public function insertRegistrantInfo($fname, $lname) {
$query = $this->db->prepare("INSERT INTO `registrants_info` (`first_name`, `last_name`) VALUES (?,?)");
$query->bindValue(1, $fname);
$query->bindValue(2, $lname);
try {
$row = $query->execute();
$insertId = $query->lastInsertId(); // <!-- Use this instead of a second query
#mail function can be added here
}catch(PDOException $e) {
die($e->getMessage());
}
}
Its also important to note that you are not inserting the 'email address' into your database, so there is no way for the query to find it by that field if you were to use another SELECT statement. You might want to complete your INSERT statement.
I'm still learning PDO so I might of missed something but basically I'm trying to insert a row into a table and then select the generated id.
I'm not sure if it likes both queries in one pdo statement. Here is the code I'm using to execute the SQL.
public function ExecuteQuery($sql, $params = array())
{
if($this->_handle == null)
$this->Connect();
$query = $this->_handle->prepare($sql);
foreach($params as $key => $value)
{
if(is_int($value)){
$query->bindValue(':'.$key, $value, \PDO::PARAM_INT);
}else if(is_bool($value)){
$query->bindValue(':'.$key, $value, \PDO::PARAM_BOOL);
}else if(is_null($value)){
$query->bindValue(':'.$key, $value, \PDO::PARAM_NULL);
}else{
$query->bindValue(':'.$key, $value, \PDO::PARAM_STR);
}
}
$query->execute();
$x = $query->fetchAll(\PDO::FETCH_ASSOC);
var_dump($x);
return $x;
}
This function is part of a database class, $this->_handle is the PDO object.
public function Connect()
{
try {
$this->_handle = new \PDO('mysql:host='.$this->_host.';dbname='.$this->_database, $this->_username, $this->_password);
$this->_handle->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION );
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
And the SQL I'm running is this:
INSERT INTO `users` (`Username`, `Password`, `PasswordSalt`, `Email`, `IsAdmin`, `LoginAttempts`, `LastLogin`, `LastLoginAttempt`, `Created`) VALUES (:username, :password, :passwordsalt, :email, :isadmin, :loginattempts, :lastlogin, :lastloginattempt, :created); SELECT LAST_INSERT_ID() as 'id'
The user is created and is there in the users table but it errors after that.
Can anyone see what am doing wrong? :)
Cheers!
I'm pretty sure the mysql driver for PDO (maybe mysql itself?) does not support multi-query prepared statements.
Instead of SELECT LAST_INSERT_ID() in your query, use Conexion::$cn->lastInsertId() after your $query->execute()
I think this is correct:
function ExecuteQuery($sql, $params = array())
{
if(Conexion::$cn== null)
Conexion::Connect();
$paramString="";
foreach($params as $k=>$v)
{
$param = " :".$k." ,";
$paramString .= $param;
}
$sql.=substr($paramString,0,-2);
$query = Conexion::$cn->prepare($sql);
foreach($params as $key => $value)
{
echo "entro";
$query->bindParam(":".$key, $value);
}
$query->execute();
$x = $query->fetchAll(\PDO::FETCH_ASSOC);
var_dump($x);
return $x;
}
public function Connect()
{
try {
$dns='dblib:host='.Conexion::$server.";dbname=".Conexion::$db.";";
Conexion::$cn = new \PDO($dns, Conexion::$user, Conexion::$passw);
Conexion::$cn->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION );
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}