Laravel 4 DB transactions not committing and rollbacking - php

I am using laravel 4 and trying to use commit and rollback functions. But functions are not working for me.
I am following laravel documentations (https://laravel.com/docs/4.2/database#database-transactions) but still its not working.
Here is my code :
DB::transaction(function() use ($product)
{
DB::table('products')->insert($product);
DB::rollBack();
});
Its creating new entry in products table. which is wrong.

In your example, the transaction will only be rolled back when there is an exception.
Note: Any exception thrown within the transaction closure will cause the transaction to be rolled back automatically.
You have to manually start your transaction with DB::beginTransaction() and end it with DB::rollback() or DB::commit()
It is also possible to do this within a try catch statement.
try {
DB::beginTransaction();
// Do something
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
}

Related

Nested Transactions in Laravel 4.2 and MySQL

In reference to this point: https://www.php.net/manual/en/pdo.begintransaction.php#109753
The following code works, but can it be run safely on production?
DB::beginTransaction();
try {
// update statements
DB::transaction(function(){
// update statements
});
// update statements
DB::commit();
} catch (Exception $e) {
DB::rollback();
}
Yes, it helps maintain the atomic state either the data gets stored or rollback.

Laravel: How to verify DB::transaction function is working or not?

I have used DB::transaction function in my controller like this,
public function store(){
$plant = new Plant;
DB::transaction(function()
{
Plant::create(request(['name','plant_code','place']));
});
}
I want to know the way I have used the function is ok and i need to verify is it working correctly?
As the documentation illustrate you have two choices :
Automatic transaction with Closure :
You may use the transaction method on the DB facade to run a set of
operations within a database transaction. If an exception is thrown
within the transaction Closure, the transaction will automatically be
rolled back. If the Closure executes successfully, the transaction
will automatically be committed. You don't need to worry about
manually rolling back or committing while using the transaction
method
DB::transaction(function () {
// Interacting with the database
DB::insert(...);
DB::insert(...);
DB::insert(...);
});
Manually Using Transactions :
If you would like to begin a transaction manually and have complete control over rollbacks and commits, you may use the beginTransaction method on the DB facade:
DB::beginTransaction();
You can rollback the transaction via the rollBack method:
DB::rollBack();
Lastly, you can commit a transaction via the commit method:
DB::commit();
The manually use of the transactions is linked to the try catch block like this :
DB::beginTransaction();
try {
// Interacting with the database
DB::insert(...);
DB::insert(...);
DB::insert(...);
DB::commit(); // Commiting ==> There is no problem whatsoever
} catch (\Exception $e) {
DB::rollback(); // rollbacking ==> Something went wrong
}
For testing the transaction you can run your example without throwing any exception ==> expected result : all fine the Plant will be created.
And if you throw an exception the transaction will be rollbacked and the Plant will not be created in the database :
public function store(){
$plant = new Plant;
DB::transaction(function()
{
Plant::create(request(['name','plant_code','place']));
throw new ModelNotFoundException("Just for testing :)");
});
}
Add use Illuminate\Database\Eloquent\ModelNotFoundException; at the top of the controller ;)

How to execute a block of php code if a transaction using eloquent fails (Laravel 5.3)?

I want to remove the directory that gets created when I record in the database is inserted. I have something like this.
$model->dir = MyClass->createDirectory();
\DB::transaction(function(){
$model->save(); // fails
});
MyClass->removeDirectory(); //this will be execute upon failure.
I'm not asking about try catch block with transactions. I am asking how to execute a block of code if transaction fails.
Delete the directory created after rollback in the transaction using try catch.
DB::beginTransaction();
try{
$model->save();
DB::commit();
}catch(\Exception $e){
DB::rollback();
// After rollback delete directory created
// write code to delete directory here.
}

What is the difference between DB::beginTransaction() and DB::transaction()?

I'm using Laravel 5.2.
I would like to know what are the differences between :
DB::beginTransaction() and DB::transaction()
DB::commitTransction() and DB::commit()
DB::rollbackTransction() and DB::rollback()
Any helps would be appreciated.
DB::beginTransaction() will only begin a transaction, while for DB::transaction() you must pass a Closure function that will be executed inside a transaction.
So this:
DB::transaction(function() {
// Do something and save to the db...
});
is the same as this:
// Open a try/catch block
try {
// Begin a transaction
DB::beginTransaction();
// Do something and save to the db...
// Commit the transaction
DB::commit();
} catch (\Exception $e) {
// An error occured; cancel the transaction...
DB::rollback();
// and throw the error again.
throw $e;
}
As you can see, DB::transaction() is a "helper" function to avoid writing code to catch errors, begin a transaction, commit the transaction, and optionally rollback (cancel the transaction) if an error occured.
If you have a more complex logic, or need an specific behaviour, you will manually build your transaction; if your logic is rather simple, DB::transaction() is the way to go.
As for DB::commitTransaction() and DB::rollbackTransaction(), I can't find information.
It's a good practice to check the source code of the things you use, because you will learn how they are written, as well as how to write. Here's the file with the source for these methods.
From Laravel 6 to use Transactions must be use the following helper functions.
use Illuminate\Support\Facades\DB;
try {
// For Begin a transaction
DB::beginTransaction();
// Do something
// Commit the transaction
DB:: commit();
} catch (\Throwable $e) {
// An error occured
DB::rollback();
// and throw the error again.
throw $e;
}
if you use the DB::commitTransaction(); function, get error undefined function.

PHP, PDO, and Exceptions

I'm currently in a bit of a dilemma regarding PDO. I've recently switched to using it from my own custom database class as I want to take advantage of transactions. The problem I'm facing is how to throw exceptions from inside a block of code that is already wrapped with try/catch for PDO. Here is an example...
try {
// PDO code
// Transaction start
// Throw manual exception here if error occurs (transaction rollback too)
// Transaction commit
} catch (PDOException $e) {
// Transaction rollback
// Code to handle the exception
}
Taking the above code example and bearing in mind that the PHP manual says; "You should not throw a PDOException from your own code". How would I handle my own exceptions and the PDO ones? Some kind of nesting?
try {
// PDO code
// Transaction start
// Throw manual exception here if error occurs (transaction rollback too)
throw new MyException("all went tits up");
// Transaction commit
} catch (PDOException $e) {
// Transaction rollback
// Code to handle the exception
} catch (MyException $e) {
// Transaction rollback
// Code to handle the exception
}
The thing is, you're going to have duplicate code which wont smell too nice. I would recommend just catching "Exception" e.g.:
try {
// PDO code
// Transaction start
// Throw manual exception here if error occurs (transaction rollback too)
throw new MyException("all went tits up");
// Transaction commit
} catch (Exception $e) {
// Transaction rollback
// Code to handle the exception
}
try{
//code here
}
catch(PDOException $e){
//handle PDO
throw $e; //to rethrow it upper if need
}
catch(Exception $e){
//handle any other
}
If something is going wrong PDO will generate exception. But if you make some changes in db and would like to revert all you can run
throw new PDOException(....);

Categories