发生错误时,laravel不会回滚(删除插入的记录)

时间:2019-03-22 08:48:24

标签: php mysql laravel eloquent

我有这个简单的功能,我想进行laravel交易。它正在插入第一个(SecondaryShare),而第二个(Primary Share)包含错误,一旦发生错误,我想回滚并删除SecondaryShare。

try {
    DB::transaction(function () use ($request) {
        $Share = new SecondaryShares();
        $Share->secondary_name = $request->secondaryName;
        $Share->primary_id = $request->primaryId
        $Share->save();

        //error in primaryname==> correct is primary_name
        $Share = new PrimaryShares();
        $Share->primaryname = $request->primaryName;
        $Share->percentage = $request->percentage;
        $Share->visibility = $visibility;
        $Share->save();
    });
} catch (\Exception $e) {
    dd('failed');
}
dd('worked');

我该如何解决?

谢谢。

2 个答案:

答案 0 :(得分:3)

您使用交易系统的方式错误。有两种方法可以使用它,并且您将它们混在一起,尽管绝对不要这样做。

选择1:交易结束

您可以将代码放入事务关闭中。一旦引发Exception(实际上是Throwable)或从这些类型继承的任何异常类型,交易将被回滚,并且异常将被重新抛出关闭处理程序:

DB::transaction(function () {
    $model1 = MyModel::create();

    // model2 will not be created if model1 couldn't be created
    $model2 = MyModel::create();
});

您还可以使用try-catch包裹事务关闭以捕获任何事务异常:

try {
    DB::transaction(function () {
        $model1 = MyModel::create();

        // model2 will not be created if model1 couldn't be created
        $model2 = MyModel::create();
    });
} catch (\Exception $e) {
    Log::error('Insert failed', ['exception' => $e]);
    return redirect()->back()->withInput();
}
return redirect()->route('form.success');

选项2:交易控制

或者,您也可以自己控制事务逻辑。但是要小心,这种方式更危险,因为它很容易发生,忘记了回滚或提交:

DB::beginTransaction();

$model1 = MyModel::create();
if ($model1->exists !== true) {
    DB::rollBack();
    Log::error('Insert 1 failed');
    return redirect()->back()->withInput();
}

$model2 = MyModel::create();
if ($model2->exists !== true) {
    DB::rollBack();
    Log::error('Insert 2 failed');
    return redirect()->back()->withInput();
}

DB::commit();
return redirect()->route('form.success');

我认为,使用选项2会产生更多的代码,并且可读性较低。


顺便说一句,Laravel使用自定义数据库异常。它将抛出\Illuminate\Database\QueryException而不会抛出\PDOException

答案 1 :(得分:0)

我的数据库是InnoDB,但我发现这些表是MyISAM。 通过向迁移添加以下代码来解决: $ table-> engine =“ InnoDB”;