从其他控制器调用的laravel事务

从其他控制器调用的laravel事务,laravel,transactions,Laravel,Transactions,如果我在BaseController中有一个函数,其中有这样一个事务 public static function add_lead_logs($lead_id, $module, $action) { DB::beginTransaction(); $lead_log = new LeadLogsModel(); $lead_log->lead_id = $lead_id; $lead_log->create_by

如果我在BaseController中有一个函数,其中有这样一个事务

public static function add_lead_logs($lead_id, $module, $action)
{
    DB::beginTransaction();

    $lead_log               = new LeadLogsModel();
    $lead_log->lead_id  = $lead_id;
    $lead_log->create_by    = Session::get('SESS_USER_ID');
    $lead_log->module       = $module;
    $lead_log->action       = $action;
    if(!$lead_log->save())
    {
        DB::rollback();

        return false;
    }
    else
    {
        DB::commit();

        return true;
    }
}
然后我在控制器中调用这个函数,比如说我在更新一些东西

DB::beginTransasction()

$lead = LeadModel::find(1);
$lead->status = '1';
if($lead->save())
{
   if($this->add_lead_logs($id,$module,$action))
   {
        DB::commit();
   }
}
else
{
   DB::rollback();
}

我怎么能只有一笔交易?我不确定出现错误时是否会成功回滚。

Laravel通过事务计数器支持嵌套事务
DB::beginTransaction()
递增计数器,而
DB::commit()
DB::rollback()
递减计数器

实际的数据库提交/回滚操作仅发生在最外层的事务调用上。如果要手动调用
DB::beginTransaction()
DB::commit()
DB::rollback()
方法,则需要确保始终将它们配对

对于当前代码,如果
$lead->save()
返回true,而
$this->add_lead_logs()
返回false,则将输入一个不会在最外层事务上调用提交/回滚的代码路径。您需要在此处的else条件中添加回滚

if($lead->save()) {
    if($this->add_lead_logs($id,$module,$action)) {
        DB::commit();
    } else {
        // make sure to rollback if add_lead_logs failed
        DB::rollback();
    }
} else {
    DB::rollback();
}

这将确保对于所有代码路径,事务将始终被提交或回滚。

这意味着,我可以删除add_lead_日志中的db:transaction?这取决于您的业务逻辑。事务的思想是能够将多个insert/update语句分组到一个全有或全无的情况中。在事务中有一条insert/update语句是没有意义的。但是,如果您的
LeadLogsModel
模型上有一个保存事件,该事件也插入/更新了数据,那么该事务将是有意义的,以确保该逻辑与LeadLogsModel模型的成功保存相关联。