PHP PDO - There is no active transaction - php

I am having problem with transactions in php script. I would like to make multiply queries and be able to recall them all, if at least one of them fails. Below you can find a simple example of the script I am using:
$tags_input = array(6,4,5);
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',
DB_USER, DB_PASSW, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
$conn->beginTransaction();
$sql = "INSERT INTO projects (id, pr_id, enabled) VALUES ( :val0, :val1, :val2)";
$stmt = $conn->prepare($sql);
if(count($tags_input)>0){
for($i = 0;$i<count($tags_input);$i++){
$stmt->bindValue(':val0', 57);
$stmt->bindValue(':val1', $tags_input[$i]);
$stmt->bindValue(':val2', 'Y');
$result = $stmt->execute();
}
}
$res1 = $conn->commit();
$conn->rollBack();
Now, this example generates an error:
Uncaught exception 'PDOException' with message 'There is no active
transaction'
If I erase the line $conn->rollBack();, the error disappears. Therefore I cannot understand, why pdo object can't see open transaction (begintransaction and commit do not generate any errors). I also tried putting rollBack() inside the transaction, but made no difference. I was still getting an error 'There is no active transaction'.
I am running PHP 5.6 and Mysql tables on InnoDB.

Wrap your transaction code inside a try-catch statement.
//try {
$tags_input = array(6,4,5);
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',
DB_USER, DB_PASSW, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$conn->beginTransaction();
$sql = "INSERT INTO projects (id, pr_id, enabled) VALUES ( :val0, :val1, :val2)";
$stmt = $conn->prepare($sql);
if(count($tags_input)>0){
for($i = 0;$i<count($tags_input);$i++){
$stmt->bindValue(':val0', 57);
$stmt->bindValue(':val1', $tags_input[$i]);
$stmt->bindValue(':val2', 'Y');
$result = $stmt->execute();
}
}
$res1 = $conn->commit();
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
EDIT
A really well-based and straight-forward explanation of the answer was provided by Richard as a comment.
The reason you got error is because you were trying to close a transaction when it was already closed. beginTransaction opens one, and EITHER rollBack OR commit closes it. You have to avoid doing BOTH actions, meaning commit/rollback, for a single beginTransaction statement, or you'll get an error. The above try/catch code ensures that only one closing statement is executed.

Peter and Richards answers are already correct, but there is one little mistake in the code from the transaction structure (and i can't add a comment).
The $connection->beginTransaction() must be outside of the try-catch block. When you're start the beginTransaction() in the try-block and your Database Operations throws an exception, the catch-block doesn't know something from an active transaction. So, you get the same error:
"There is no active transaction".
So the structure should be as well:
Get the Connection.
Start the Transaction with $connection->beginTransaction()
Open the try-catch block.
The try-block contains the $connection->commit() after DB Operations.
The catch-block contains the $connection->rollback() before a throw Exception.
So your code should look like this:
$tags_input = array(6,4,5);
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',
DB_USER, DB_PASSW, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
//Begin Transaction
$conn->beginTransaction();
try {
$sql = "INSERT INTO projects (id, pr_id, enabled) VALUES ( :val0, :val1, :val2)";
$stmt = $conn->prepare($sql);
if(count($tags_input)>0){
for($i = 0;$i<count($tags_input);$i++){
$stmt->bindValue(':val0', 57);
$stmt->bindValue(':val1', $tags_input[$i]);
$stmt->bindValue(':val2', 'Y');
$result = $stmt->execute();
}
}
$res1 = $conn->commit();
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}

Related

PDO Delete Query in PHP does not take effect

I am using the below code to delete all rows from the mysql table but it does not take any effect. I am also not getting any errors - it just says record Record deleted successfully. I don't know if there is any backend safe mode enabled or I need to do additional commits but all the data is still in the database.
<?php
try {$pdo = new PDO("mysql:host=mysql;dbname=menu;charset=utf8mb4", "user",
"pass", array(PDO::ATTR_PERSISTENT => true));
} catch (\PDOException $e) {throw new \PDOException($e->getMessage(), (int)$e->getCode());};
$org = "1";
try {
$sql = "DELETE FROM menu where org=?";
$pdo->prepare($sql)->execute([$org]);
echo "Record deleted successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
?>

Connecting to MYSQL using php

I am trying to connect to MYSQL using php, but when I use the following command:
$link=mysql_connect("localhost","root","password");
and echo $link, it gives me Resource id #98. What does this mean? Am I not connected?
Okay, I guess it sounds like the connection is okay. Now, with the following code, I am not seeing any changes in the mysql database. Why could that be?
<?php
$conn=new mysqli("localhost","root","password","database");
$sql="INSERT INTO chat_active (user, time)
VALUES('John', '1234')";
?>
What makes you think you are not connected?
According to the docs, mysql_connect()
[r]eturns a MySQL link identifier on success or FALSE on failure.
Since it did not return FALSE, but rather a resource identifier, that means the connection was successful.
Also note that the mysql extension is deprecated since PHP 5.5.0 as MortimerCat pointed out. Instead you should look into the MySQLi or the PDO extension.
"Now, with the following code, I am not seeing any changes in the mysql database. Why could that be?"
As per your edit which you are now using mysqli_ to connect with, and that you're saying that you're not seeing any changes in your database, is because:
You're not passing the DB connection to your query and it is required when using mysqli_.
Rewrite, with a few more goodies:
<?php
$conn=new mysqli("localhost","root","password","database");
// Check if you've any errors when trying to access DB
if ($conn->connect_errno) {
printf("Connect failed: %s\n", $conn->connect_error);
exit();
}
$sql="INSERT INTO chat_active (user, time) VALUES ('John', '1234')";
$result = $conn->query($sql);
// Check if you've any errors when trying to enter data in DB
if (!$result)
{
throw new Exception($conn->error);
}
else{
echo "Success";
}
Read the manual http://php.net/manual/en/mysqli.query.php
Once you've grasped that, get to know mysqli with prepared statements, or PDO with prepared statements, they're much safer.
References:
http://php.net/manual/en/book.mysqli.php
http://php.net/manual/en/mysqli.query.php
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/language.exceptions.php
Footnotes:
Your column names user, time suggests that you're trying to enter a string and what appears to be and to be intended as "time" and that the user column is set to varchar.
Make sure that you haven't setup your time column other than a datetime-related type, otherwise MySQL may complain about that.
MySQL stores dates as YYYY-mm-dd as an example.
Visit https://dev.mysql.com/doc/refman/5.0/en/datetime.html in regards to different date/time functions you can use.
MySQL references:
https://dev.mysql.com/doc/refman/5.0/en/char.html
https://dev.mysql.com/doc/refman/5.0/en/data-types.html
https://dev.mysql.com/doc/refman/5.0/en/datetime.html
You yould use mysqli or PDO.
Here's a connection example with PDO:
<?php
$dbuser = 'user';
$dbpasswd = 'passwd';
$dbname = 'dbname';
try {
$gbd = new PDO("mysql:host=localhost;dbname=$dbname;charset=utf8", $dbuser, $dbpasswd);
$gbd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo $e->getMessage();
}
PDO CRUD examples:
//INSERT
try {
$sentence = $gbd->prepare("INSERT INTO table (param1, param2) VALUES (:param1, :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
//SELECT
try {
$sentence = $gbd->prepare("SELECT param1,param2 FROM table WHERE param1 = :param1 AND param2 = :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
while ($row = $sentence->fetch(PDO::FETCH_ASSOC)){ //Also available FETCH_NUM,FETCH_BOTH AND OTHERS
$result['param1'] = $row['param1'];
$result['param2'] = $row['param2'];
}
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
//UPDATE
try {
$sentence = $gbd->prepare("UPDATE table SET param1 = :param1, param2 = :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
//DELETE
try {
$sentence = $gbd->prepare("DELETE table WHERE param1 = :param1 AND param2 = :param2)");
$sentence->bindParam(':param1', $param1);
$sentence->bindParam(':param2', $param2);
$sentence->execute();
}
catch (PDOException $e) {
echo 'Query failed: ' . $e->getMessage();
}
And here's PDO manual
http://php.net/manual/en/book.pdo.php
u are not executing that query.u are only declaring that query.
for execution do--
$conn->query($qry);
it will,execute ur query.

pdoexception not outputting error

$db = new PDO('mysql:host=localhost;dbname=dbname;charset=utf8', 'username', 'password');
try
{
//Prepare and execute an insert into DB
$st = $db->prepare("INSERT INTO users(login,pass,email,county) VALUES(:username,:password,:email,:county)");
$st->execute(array(':username' => $_POST['username'], ':password' => $_POST['password1'], ':email' => $_POST['email'], ':county' => $_POST['county']));
echo 'Success';
}
catch (PDOException $e)
{
echo $e->getMessage();
}
Hi, I am not completely familiar with pdo but I thought I would add a few error exceptions, except I won't actually display the error normally as I don't want everyone to know my schema. In this case I changed my working code to a non working code by changing "...,county)" to "....,count)" which obviously did not insert into the database at all but still shown "Success" and no error.
Please help :(
You need to set PDO error mode to throw exception.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

PHP PDO Doesn't insert new records

I do not understand what my problem seem to be.
I got the following PHP code:
include_once 'db.inc.php';
try
{
$db = new PDO(DB_INFO, DB_USER, DB_PASS);
}
catch(PDOException $e)
{
echo 'Connection failed: ', $e->getMessage();
exit();
}
$title = htmlentities($_POST['title']);
$entry = htmlentities($_POST['entry']);
$sql = "INSERT INTO entries (title, entry) VALUES (?, ?)";
$stmt = $db->prepare($sql);
$stmt->execute(array($title, $entry));
$stmt->closeCursor();
I do not receive any error of any kind and the script seem to have worked however it does not insert anything into the database.
No matter what I try it doesn't do anything.
edit
Sorted :)
I didn't know about $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);.
It gave me "Uncaught exception 'PDOException' with message 'SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected'".
Turns out I wrote mysql:host=127.0.0.1;db_name=test1 instead of mysql:host=127.0.0.1;dbname=test1 in my config file.
Thank you very much for help!
Set PDO to throw exceptions when execution fails
$db = new PDO(DB_INFO, DB_USER, DB_PASS);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

PDO connection try catch include

I'm new to PDO and I wanna do it right from the beginning - I'm going to replace my old mysql_ functions on a site.
Have I got it right?:
Should I put the connection code in a try/catch and save it to a file, and include it on top of the page. Then put the queries in try/catch as well.
Or:
Should I put the connection code in a file and include it in the in the top of the try/catch statement above the query?
ver1:
include('pdo.php'); // try/catch in file
try {
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
ver2:
try {
include('pdo.php'); // no try/catch in file
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
Or should I put the try/catch in both places?
You should do both and even more :
Set an error handler that displays a message to the user and stops the PHP (see set_error_handler)
When you initiate the connexion, add a try/catch and throw an error if you catch an exception. Your website won't run without database connection i guess.
Do a try/catch around your queries to recover gracefully from error (when you can)

Categories