Метод transaction
Метод transaction класса DB предоставляет возможность выполнять операции с базой данных в рамках транзакции. Транзакция гарантирует, что все операции внутри неё будут выполнены успешно, либо, в случае ошибки, все изменения будут отменены. Метод принимает замыкание, в котором выполняются все операции. Если внутри замыкания возникает исключение, транзакция автоматически откатывается. Также метод поддерживает указание уровня изоляции транзакции и количество попыток повторного выполнения в случае возникновения ошибок.
Синтаксис
<?php
DB::transaction(Closure $callback, int $attempts = 1, int $isolationLevel = null);
?>
Параметр $callback содержит замыкание с операциями базы данных. Параметр $attempts определяет количество попыток выполнения транзакции при возникновении ошибок блокировки. Параметр $isolationLevel позволяет указать уровень изоляции транзакции.
Пример
Давайте выполним перенос средств между пользователями в рамках одной транзакции:
<?php
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
$user1 = DB::table('users')->where('id', 1)->first();
$user2 = DB::table('users')->where('id', 2)->first();
$amount = 100;
DB::table('users')->where('id', 1)->update([
'balance' => $user1->balance - $amount
]);
DB::table('users')->where('id', 2)->update([
'balance' => $user2->balance + $amount
]);
});
echo "Transaction completed successfully";
?>
Результат выполнения кода:
"Transaction completed successfully"
Пример
Обработаем случай, когда во время транзакции возникает ошибка:
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
try {
DB::transaction(function () {
DB::table('orders')->insert([
'user_id' => 1,
'total' => 500,
'status' => 'pending'
]);
DB::table('products')->where('id', 1)->update([
'quantity' => DB::raw('quantity - 5')
]);
throw new Exception('Something went wrong');
});
} catch (Exception $e) {
Log::error('Transaction failed: ' . $e->getMessage());
}
?>
В этом случае транзакция будет откачена, и данные не будут изменены. Результат в логах:
"Transaction failed: Something went wrong"
Пример
Используем транзакцию с несколькими попытками выполнения:
<?php
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
$user = DB::table('users')->where('id', 1)->lockForUpdate()->first();
if ($user->balance >= 50) {
DB::table('users')->where('id', 1)->update([
'balance' => $user->balance - 50
]);
DB::table('transactions')->insert([
'user_id' => 1,
'amount' => -50,
'type' => 'withdrawal'
]);
}
}, 5);
echo "Transaction with retries completed";
?>
Результат выполнения кода:
"Transaction with retries completed"
Смотрите также
-
метод
beginTransaction,
который начинает транзакцию вручную -
метод
commit,
который фиксирует изменения в транзакции -
метод
rollBack,
который откатывает транзакцию -
метод
connection,
который позволяет получить экземпляр соединения с базой данных