Transaction does not work for subfunctions

I use DB::beginTransaction() in Laravel, but it only works for database changes that are executed in the main function, and not for helper functions.

Main function code:

 try { DB::beginTransaction(); $data = array( 'id' => Input::get('id'), 'task_title' => Input::get('task_title'), ); DB::table('task')->insert($data); $id = DB::getPdo()->lastInsertId(); // Add Actionees if (!$this->addActionees(Input::get('actionees'), $id)) { DB::rollback(); return Response::json(false); } DB::commit(); return Response::json(true); } catch (Exception $ex) { DB::rollback(); return Response::json($ex); } 

Function Code:

 private function addActionees($actionees, $id, $status) { try { DB::table('task_assignee_user')->where('task_id', $id)->delete(); foreach ($actionees as $act) { $actAdd = array( 'task_id' => $id, 'user_id' => $act->user_id, ); DB::table('task_assignee')->insert($actAdd); } return True; } catch (Exception $ex) { return FALSE; } } 

So, in the above example, the changes that are made under the addActionees() functions addActionees() not rolled back. In the addActionees() function, the entire record against the identifier is deleted before inserting new records. If an exception is found, I want to return these changes.

+5
source share
5 answers

If you wrap the entire transaction inside the closure, it will process everything for you :

 public mainFunction() { try { DB::transaction(function() { $id = DB::table('task')->insertGetId(['id' => Input::get('id'), 'task_title' => Input::get('task_title')]); DB::table('task_assignee_user')->where('task_id', $id)->delete(); foreach(Input::get('actionees') as $act) { DB::table('task_assignee')->insert(['task_id' => $id, 'user_id' => $act->user_id]); } }); } catch (\Exception $e) { return Response::json($e); } return Response::json(true); } 

ps I also reorganized your code as it drove me crazy. This should work, but I have not tested it, but you get a general idea.

+1
source

You should not catch an exception in the addActionees () method. Just leave it thrown and the external try-catch block will process it:

Main function code:

 try { DB::beginTransaction(); $data = array( 'id' => Input::get('id'), 'task_title' => Input::get('task_title'), ); DB::table('task')->insert($data); $id = DB::getPdo()->lastInsertId(); // Add Actionees $this->addActionees(Input::get('actionees'), $id); DB::commit(); return Response::json(true); } catch (Exception $ex) { DB::rollback(); return Response::json($ex); } 

Helper Function Code:

 private function addActionees($actionees, $id, $status) { DB::table('task_assignee_user')->where('task_id', $id)->delete(); foreach ($actionees as $act) { $actAdd = array( 'task_id' => $id, 'user_id' => $act->user_id, ); DB::table('task_assignee')->insert($actAdd); } } 
+1
source

In the main function: beginTransaction above try{

 DB::beginTransaction(); try { $data = array( ... 
0
source

It only works when using DB::beginTransaction() in a subfunction, but this is not the answer to my question:

Main function code:

 try { DB::beginTransaction(); $data = array( 'id' => Input::get('id'), 'task_title' => Input::get('task_title'), ); DB::table('task')->insert($data); $id = DB::getPdo()->lastInsertId(); // Add Actionees if (!$this->addActionees(Input::get('actionees'), $id)) { DB::rollback(); return Response::json(false); } DB::commit(); return Response::json(true); } catch (Exception $ex) { DB::rollback(); return Response::json($ex); } 

Function Code:

 private function addActionees($actionees, $id, $status) { DB::beginTransaction(); try { DB::table('task_assignee_user')->where('task_id', $id)->delete(); foreach ($actionees as $act) { $actAdd = array( 'task_id' => $id, 'user_id' => $act->user_id, ); DB::table('task_assignee')->insert($actAdd); } DB::commit(); return True; } catch (Exception $ex) { DB::rollback(); return FALSE; } } 
0
source

Try using a transaction through a stream as follows:

 DB::beginTransaction(); try { $data = array( 'id' => Input::get('id'), 'task_title' => Input::get('task_title'), ); DB::table('task')->insert($data); $id = DB::getPdo()->lastInsertId(); // Add Actionees $this->addActionees(Input::get('actionees'), $id); } catch (Exception $ex) { DB::rollBack(); return Response::json($ex); } DB::commit(); return Response::json(true); private function addActionees($actionees, $id, $status) { DB::table('task_assignee_user')->where('task_id', $id)->delete(); foreach ($actionees as $act) { $actAdd = array( 'task_id' => $id, 'user_id' => $act->user_id, ); DB::table('task_assignee')->insert($actAdd); } } 
  • Start a transaction.
  • Perform CRUD operations.
  • Exclude and discard the transaction.
  • If operations are performed smoothly, complete the transaction.

Edit:

addActionees always returns true because the delete() method does not throw an exception while execution is in progress. Therefore, $this->addActionees(Input::get('actionees'), $id) always returns true. Throw an exception manually:

 private function addActionees($actionees, $id, $status) { $deleteResult = DB::table('task_assignee_user')->where('task_id', $id)->delete(); foreach ($actionees as $act) { $actAdd = array( 'task_id' => $id, 'user_id' => $act->user_id, ); DB::table('task_assignee')->insert($actAdd); } if ($deleteResult == 0) { throw new Exception('Delete failed'); } } 
0
source

Source: https://habr.com/ru/post/1270432/


All Articles