Laravel: Using Try...Catch with Db::Transaction()

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



Leave a reply



Submit