laravel не откатывается (удаляет вставленные записи) при возникновении ошибки - PullRequest
0 голосов
/ 22 марта 2019

У меня есть эта простая функция, и я хочу сделать транзакцию 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 ]

3 голосов
/ 22 марта 2019

Вы неправильно используете систему транзакций. Есть два способа его использования, и вы их путаете, хотя этого никогда не следует делать.

Вариант 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.

0 голосов
/ 22 марта 2019

Моя база данных - InnoDB, но я выяснил, что таблицы - MyISAM. решается добавлением этой строки кода для миграции: $ table-> engine = "InnoDB";

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...