Laravel 4-db事务保存同时自动创建其他模型 [英] Laravel 4 - db transaction on save while automatically creating other model

查看:138
本文介绍了Laravel 4-db事务保存同时自动创建其他模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个模型:UserPayout和UserTransaction,其中UserTransaction是多态的,需要知道它属于哪个模型。
每当用户创建付款时,都应自动进行交易。如果在这个过程中出现问题,两者都应该回滚。

I have two models: UserPayout and UserTransaction where UserTransaction is polymorph and needs to know which model it belongs to. Whenever a user creates a payout, a transaction should automatically be made. If something went wrong in this process, both should get rolled back.

我的实际解决方案如下:

My actual solution is as follows:

控制器:

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

UserPayout:

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:

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;
}

嗯,这个解决方案实际上可以工作,但是如果我需要更新一个支付?它将触发保存功能,(当然)会创建一个新的事务。这是绝对错误的。

Well, this solution would actually work but what if I need to update a payout? It would trigger the save function and (of course) it would create a new transaction. This is absolutely wrong.

那么解决方案只能应用于创建付款?

So what would be the solution to only apply it on a creation of a payout?

我想到了像创建和创建的事件。在创建的情况下,由于尚未创建付款,因此无法将其所属的交易模型告知其所属的事务模型。另一方面,在创建的情况下,我无法确定在保存交易时是否出现问题,以便我可以回滚支付。

I thought about events like creating and created. In case of creating I can't tell the transaction model to whom it belongs because the payout isn't created yet. On the other hand in case of created I can't tell if something went wrong while saving a transaction so that I could rollback the payout.

那么什么是正确的解决方案任何帮助是赞赏。

So what would be the right solution here? Any help is appreciated.

推荐答案


那么解决方案只适用于创建付款? / p>

So what would be the solution to only apply it on a creation of a payout?

您可以通过检查您的 save()方法:

You can easily determine if a payout is created or updated by checking if the id is set in your save() method:

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

其次,如果你看在如何口才处理交易中,您将看到它们不会嵌套。只有调用堆栈中第一次调用 beginTransaction()才会启动DB事务,只有最后一次调用 commit()才能提交事务,因此您不需要担心嵌套事务。

Secondly, if you look at how Eloquent handles transactions, you'll see that they won't nest. Only the first call to beginTransaction() in the call stack starts a DB transaction and only the last call to commit() commits the transaction, so you don't need to worry about nested transactions.

说到事件,他们提供了很好的分离问题和使用会使您的代码更加灵活。这是不正确的你写的:

And speaking of events, they provide a nice separation of concerns and using would make your code more flexible. It's not correct what you write:


如果创建我不能告诉交易模型给
属于谁付款尚未创建。另一方面,在
创建的情况下,我无法确定在保存
事务时出现问题,以便我可以回滚支付。

In case of creating I can't tell the transaction model to whom it belongs because the payout isn't created yet. On the other hand in case of created I can't tell if something went wrong while saving a transaction so that I could rollback the payout.

创建事件中调用的回调获取已知类型的对象。你不会有ID,这是真的。但是您仍然可以将此模型与其他模型相关联,并且Eloquent将正确设置外键。只需确保直接使用关联方法,如 associate(),而不是只设置外键值,因为尚未设置ID:

The callback that is called on creating event gets an object of known type. You won't have ID, that's true. But you can still associate this model with other models and Eloquent will set the foreign keys correctly. Just make sure you use relation methods like associate() directly and not just set a value of a foreign key, as IDs have not been set yet:

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

您还应该看看 DB :: transaction() 口述提供的包装。它为您处理 begin / commit / rollback ,因此需要较少的代码:

You should also have a look at the DB::transaction() wrapper that Eloquent provides. It handles begin/commit/rollback for you so less code is required:

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

您可以在这里阅读更多关于 Laravel 中的交易: http://laravel.com/docs/5.1/database#database-transactions

You can read more about transactions in Laravel here: http://laravel.com/docs/5.1/database#database-transactions

这篇关于Laravel 4-db事务保存同时自动创建其他模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆