Intereting Posts

Laravel 4 – транзакция db при сохранении при автоматическом создании другой модели

У меня есть две модели: UserPayout и UserTransaction, где UserTransaction является полиморфной и нужно знать, к какой модели она принадлежит. Всякий раз, когда пользователь создает выплату, транзакция должна быть автоматически сделана. Если что-то пошло не так в этом процессе, оба должны вернуться.

Мое фактическое решение выглядит следующим образом:

контроллер:

$user_payout = new UserPayout($input); $user->payouts()->save($user_payout); 

UserPayout:

 public function save(array $options = Array()) { DB::beginTransaction(); try{ parent::save($options); $transaction = new UserTransaction( array( 'user_id' => $this->user_id, 'template_id' => $this->template->id, 'value' => -$this->amount ) ); $this->transactions()->save($transaction); } catch(\Exception $e) { DB::rollback(); throw $e; } DB::commit(); return $this; } 

UserTransaction:

 public function save(array $options = Array()) { DB::beginTransaction(); try{ $user = User::find($this->user_id); $user->balance = $user->balance + $this->value; if(!$user->save()) throw new Exception('User could not be saved. Check for validation rules.'); parent::save($options); } catch(\Exception $e) { DB::rollback(); throw $e; } DB::commit(); return $this; } 

Ну, это решение действительно работает, но что, если мне нужно обновить выплату? Это вызовет функцию сохранения и (конечно), что создаст новую транзакцию. Это абсолютно неправильно.

Итак, каково было бы решение применить его только к созданию выплаты?

Я думал о таких событиях, как создание и создание. В случае создания я не могу сказать модели транзакции, кому она принадлежит, потому что выплата еще не создана. С другой стороны, в случае создания я не могу сказать, что что-то пошло не так во время сохранения транзакции, чтобы я мог откатить выплату.

Итак, что было бы правильным решением здесь? Любая помощь приветствуется.

Related of "Laravel 4 – транзакция db при сохранении при автоматическом создании другой модели"

Итак, каково было бы решение применить его только к созданию выплаты?

Вы можете легко определить, создается или обновляется выплата, проверяя, установлен ли идентификатор в вашем методе save () :

 if ($this->id) { //update transaction } else { //create transaction } 

Во-вторых, если вы посмотрите, как Eloquent обрабатывает транзакции, вы увидите, что они не будут вложены. Только первый вызов beginTransaction () в стеке вызовов запускает транзакцию БД, и только последний вызов commit () совершает транзакцию, поэтому вам не нужно беспокоиться о вложенных транзакциях.

И, говоря о событиях, они обеспечивают хорошее разделение проблем, и использование сделает ваш код более гибким. Неправильно, что вы пишете:

В случае создания я не могу сказать модели транзакции, кому она принадлежит, потому что выплата еще не создана. С другой стороны, в случае создания я не могу сказать, что что-то пошло не так во время сохранения транзакции, чтобы я мог откатить выплату.

Обратный вызов, вызываемый при создании события, получает объект известного типа. У вас не будет ID, это правда. Но вы можете связать эту модель с другими моделями, и Eloquent правильно установит внешние ключи. Просто убедитесь, что вы напрямую используете методы отношения, такие как associate (), а не просто устанавливаете значение внешнего ключа, поскольку идентификаторы еще не установлены:

 $transaction = new UserTransaction($data); $transaction->payout()->associate($payout); $transaction->save(); 

Вы также должны взглянуть на обертку DB :: transaction (), которую предоставляет Eloquent . Он обрабатывает начало / фиксацию / откат для вас, поэтому требуется меньше кода:

 DB::transaction(function () { // do whatever logic needs to be executed in a transaction }); 

Подробнее о транзакциях в Laravel можно узнать здесь: http://laravel.com/docs/5.1/database#database-transactions