Laravel: 使用 try...catch 来结合 DB::transaction()

9 浏览
0 Comments

Laravel: 使用 try...catch 来结合 DB::transaction()

我们都使用DB::transaction()来进行多个插入查询。在这样做的过程中,是否应该在其中放置一个try...catch,或者将其包裹起来?如果事务出现问题,是否有必要包含try...catch,因为事务会自动失败?\n示例中的try...catch包裹了一个事务:\n

// try...catch
try {
    // 事务
    $exception = DB::transaction(function() {
        // 在这里进行SQL操作
    });
    if(is_null($exception)) {
        return true;
    } else {
        throw new Exception;
    }
}
catch(Exception $e) {
    return false;
}

\n相反,DB::transaction()包裹了一个try...catch:\n

// 事务
$exception = DB::transaction(function() {
    // try...catch
    try {
        // 在这里进行SQL操作
    }
    catch(Exception $e) {
        return $e;
    }
});
return is_null($exception) ? true : false;

\n或者简单地进行事务而不使用try...catch:\n

// 仅事务
$exception = DB::transaction(function() {
    // 在这里进行SQL操作
});
return is_null($exception) ? true : false;

0
0 Comments

Laravel: 使用try...catch与DB::transaction()

在Laravel中使用DB::transaction()进行数据库事务处理时,可能会遇到一些异常情况。下面的内容提供了一个解决方法。

首先,让我们看一下Laravel中DB::transaction()的实现代码:

public function transaction(Closure $callback)
{
    $this->beginTransaction();
    try {
        $result = $callback($this);
        $this->commit();
    }
    catch (Exception $e) {
        $this->rollBack();
        throw $e;
    }
    catch (Throwable $e) {
        $this->rollBack();
        throw $e;
    }
    return $result;
}

我们可以发现,在DB::transaction()函数中,使用了try...catch块来处理可能发生的异常。如果在事务处理过程中发生了异常,将会执行rollBack()回滚操作,并将异常抛出。如果没有发生异常,将会执行commit()提交操作。

根据上述代码,我们可以在我们的代码中使用try...catch块来包裹DB::transaction(),以便处理可能出现的异常情况,并根据需要进行相应的处理。下面是一个示例代码:

try {
    $result = DB::transaction(function () use ($request, $message) {
        // 执行查询1
        // 执行查询2
        // ...
    });          
    // 重定向页面
    return redirect(route('account.article'));
} catch (\Exception $e) {
    return redirect()->back()->withErrors(['error' => $e->getMessage()]);
}

在上面的示例代码中,我们将DB::transaction()函数放在try块中,并根据需要进行异常处理。如果发生了异常,我们可以通过$e->getMessage()获取异常信息,并将其返回到表单页面上。如果没有发生异常,将会执行重定向操作。

另外,我们还可以在事务处理函数中使用返回布尔值的方式来处理异常,或者在catch块中获取异常信息。这取决于具体的需求。

需要注意的是,从2022年1月20日开始,对于"Wrap Transaction"示例代码进行了更新,以反映出一个建议。这个更新后的代码应该是正确的。同时,对于异常处理,我们可以统一使用\Exception来避免歧义。

根据上述内容,我们可以在使用Laravel中的DB::transaction()时,使用try...catch块来处理可能发生的异常情况,并根据需要进行相应的处理。这样可以更好地控制事务处理过程中的异常情况,并进行相应的回滚操作或异常信息处理。

总之,使用try...catch与DB::transaction()可以有效地处理Laravel中的数据库事务异常,并根据需要进行相应的处理和回滚操作。

0
0 Comments

Laravel: 使用try...catch结合DB::transaction()的原因和解决方法

在使用Laravel进行数据库事务处理时,我们常常会使用DB::transaction()方法来确保在执行一系列数据库操作时保持事务的完整性。然而,在进行异常处理时,我们需要注意一些细节。

首先,如果我们使用的是PHP7及以上版本,我们可以使用Throwable来捕获用户异常和致命错误。示例代码如下:

DB::beginTransaction();
try {
    DB::insert(...);    
    DB::commit();
} catch (\Throwable $e) {
    DB::rollback();
    throw $e;
}

上述代码中,我们使用了try...catch块来捕获可能出现的异常,当捕获到异常时,我们会执行DB::rollback()方法来回滚事务,并将异常继续抛出。

如果我们的代码需要与PHP5兼容,我们需要同时使用Exception和Throwable。示例代码如下:

DB::beginTransaction();
try {
    DB::insert(...);    
    DB::commit();
} catch (\Exception $e) {
    DB::rollback();
    throw $e;
} catch (\Throwable $e) {
    DB::rollback();
    throw $e;
}

上述代码中,我们使用了相同的try...catch块来捕获异常,但这次我们分别使用了Exception和Throwable来捕获不同类型的异常。

然而,我们还需要考虑到DB::beginTransaction()方法本身可能会抛出异常的情况。那么,我们是否应该将其包含在try...catch块中呢?

事实上,如果事务尚未开始,我们无需执行任何回滚操作。而且,在catch块中尝试回滚未开始的事务也是没有意义的。因此,将DB::beginTransaction()方法放在try块之前是一个比较好的选择。

总结起来,当我们使用Laravel的DB::transaction()方法进行数据库事务处理时,我们可以使用try...catch结构来捕获可能出现的异常,并在捕获到异常时执行回滚操作。同时,我们需要注意将DB::beginTransaction()方法放在try块之前,以确保事务的正确处理。

希望以上内容能对你理解Laravel中使用try...catch结合DB::transaction()的原因和解决方法有所帮助。

0
0 Comments

Laravel:使用try...catch与DB::transaction()一起使用的原因和解决方法

在需要通过代码手动“退出”事务的情况下(无论是通过异常还是简单地检查错误状态),不应该使用DB::transaction(),而是应该将代码封装在DB::beginTransaction和DB::commit()/DB::rollback()中:

DB::beginTransaction();
try {
    DB::insert(...);
    DB::insert(...);
    DB::insert(...);
    DB::commit();
    // 一切正常
} catch (\Exception $e) {
    DB::rollback();
    // 发生错误
}

DB::transaction接受一个匿名函数,用于在事务中运行的DB语句,而DB::beginTransaction()要求将DB语句写在调用旁边(如上面的示例),然后使用DB::commit()或DB::rollback()来结束事务。

简单问题:如果不在异常后执行rollback,或者不捕获异常会发生什么?脚本结束后自动回滚吗?

不幸的是,我不知道,但我想象事务会保持打开状态,继续吞噬更多的DB插入/更新,然后最后当应用结束时,整个事务都会回滚。可以很容易地编写一个快速测试脚本来尝试一下。你可能会发现你得到一个"transaction not exited"风格的异常,以及自动回滚。

Laravel 5.3数据库事务是一个大问题,它真的不起作用

这个问题是关于Laravel 4数据库的,所以我的回答对于5.3版本可能不再正确。你可以提一个带有Laravel 5.3标签的新问题,以获得正确的社区支持。

我已经尝试了很多关于Laravel 5.3.19上的DB事务,但它根本不起作用,现在我再试一次验证我的实践,我确实有更多关于这个问题的教程,但他们说这不是一个bug。让我再试一次。但是我确信这是正确的,因为我通过公司更新和安装更新了LR框架的最新版本。

如果不起作用,我如何使它起作用?

值得一提的是,我们目前在Laravel 5.5中成功使用这种模式。

不要忘记重新抛出异常,否则你的迁移将在运行器中被视为“已完成”,并且条目将被放置在你的迁移表中。

我可以在try中使用Eloquent操作吗?那样会回滚吗?

在我拔掉头发两个小时后,我发现我的表引擎是MyISAM。

你不认为DB::commit();应该在try之外吗?

对我来说,不是的。如果提交过程中出现问题,我们可能仍然希望尝试回滚。也就是说,这是一个非常古老的答案,是一个古老的Laravel问题的答案,而且我已经好几年没有正式使用PHP了,所以我对此已经不再是任何权威。甚至在提交过程中引发异常后回滚可能是不可能的,所以它可能必须移到外部,不过确保不要在rollback之后调用commit,否则如果在try部分发生异常,你将调用commit。

...如果在try块中发生异常,控制权将进入catch并执行回滚命令。即使在catch块之后的错误(在commit语句之前)中,try块中的SQL查询结果也不会保存在数据库中,因为SQL语句处于事务块中。对吗?

是的,回滚将“取消”事务。但是然后代码将尝试调用“commit”,我不知道它是否会自身出错(没有要提交的内容/不在事务中)或者它是否只是一个无操作。只是警告你,如果commit在rollback之后调用会出错的话,你可能希望确保不要在任何方式下调用commit。

出于好奇,为什么不能在try块内部使用DB::transaction()并在之后使用catch块?

0