Laravel: Using try...catch with DB::transaction()
In the case you need to manually 'exit' a transaction through code (be it through an exception or simply checking an error state) you shouldn't use DB::transaction()
but instead wrap your code in DB::beginTransaction
and DB::commit
/DB::rollback()
:
DB::beginTransaction();
try {
DB::insert(...);
DB::insert(...);
DB::insert(...);
DB::commit();
// all good
} catch (\Exception $e) {
DB::rollback();
// something went wrong
}
See the transaction docs.
Laravel 9 - transaction try catch error message
The answer is yes of course you can add a try/catch for this problem, since you plan to put this login in a cronjob there is no need to return any error message to the application, so the better option is to email the Admin with the error message, so this logic should work
public function handle() {
try {
DB::transaction(function() {
DB::table('table1')->insert([ // some data insert ]);
DB::table('table2')->insert([ // some data insert ]);
}
} catch (Exception $e) {
Mail::to('adminmail')->send($e->getMessage());
}
}
Also if you do not want to spam the admin with every error message every 10 mintues, you can add Sentry for error handling inside the app (it does cost a bit but its a life saver);
What happens to a Laravel DB Transaction if an exception is thrown?
A transaction that isn't committed will be discarded in SQL.
When you throw the exception here, DB::commit()
is never reached. You'll go straight to the catch() block and therefore the transaction will be discarded (as long as DB::commit()
isn't called somewhere later).
However, I would still always recommend explicitly rolling back the transaction in your catch block if you do not want to commit the transaction when an exception is thrown, this will close out that transaction and prevent any effect on your future queries in that execution.
try {
DB::beginTransaction();
throw new Exception("something happened");
DB::commit()
} catch (Exception $e) {
Log::debug("something bad happened");
DB::rollBack();
}
Or use the built in DB::transaction() with a closure to automatically rollback when an exception is uncaught, documented here: https://laravel.com/docs/5.3/database#database-transactions
Cleanest way to use BeginTransaction using try catch
Neither of those two methods is good. They are too verbose.
The best method is to just put the Transaction
in a using
as well, also we should use a parameter for the query:
using(var connection = new SqlConnection(connString))
using(var cmd = new SqlCommand("Insert into Customers (Name) values (@Name));"))
{
var param = cmd.Parameters.Add("@Name", SqlDbType.VarChar, insert_column_length_here);
connection.Open();
using(var transaction = connection.BeginTransaction())
{
cmd.Transaction = transaction;
param.Value = "Dimitri";
cmd.ExecuteNonQuery();
param.Value = "George";
cmd.ExecuteNonQuery();
transaction.Commit();
}
}
We can see that disposing the transaction object will automatically rollback if not already committed, by looking at the source code. So using
will clean everything up.
If you need to catch to display a message to the user, do it outside the code i.e. put a try/catch
around the whole thing. Don't do the cleanup code yourself
Laravel Transaction: How to do commit some queries instead of rollback all?
Putting the transaction inside the try block should work:
use Exception;
try {
\DB::transaction(function () use ($request) {
// operations
});
} catch (Exception $e) {
$exception_model = new ExceptionModel();
$exception_model->user = $request->user_info;
$exception_model->detail = $e;
$exception_model->save();
abort(Response::HTTP_BAD_REQUEST, 'Something went wrong');
}
laravel db transaction context is available on called functions
after several test i can tell that no closure is needed for model too, even if you have a create method inside another function, and exception is throwed -in the main or in the function- no problem with the rollback and commit steatment!
Well much more of that i was hoping!!!!
This is the code I tested:
DB::beginTransaction();
try {
$this->pippo();
} catch (\Exception $ex) {
DB::rollback();
}
DB::commit();
public function pippo(){
$type=Cga_type::create(['name'=>'vvvv','description'=>'yyy']);
throw new Exception('error');
}
If I comment the transactions functions the record is written on the db, no otherwise!!!
Related Topics
Symfony2 - Assetic - CSS Font Icons
Reordering Checkout Fields in Woocommerce 3
How to Create Static Classes in PHP (Like in C#)
How to Execute Stored Procedure from Laravel
Type Casting for User Defined Objects
Why and How to Use Anonymous Functions in PHP
Pass Extra Parameters to Usort Callback
Codeigniter, Result() VS. Result_Array()
Custom Order Status Background Button Color in Woocommerce 3.3 Admin Order List
PHP Inserting Multiple Checkbox and Textbox Arrays into MySQL Database
Why Is Textarea Filled with Mysterious White Spaces
How to Make Pdo Run Set Names Utf8 Each Time I Connect, in Zendframework
How to Create a Zip File Using PHP