[英]Transaction does not rollback when exception occurs outside controller
控制器外發生異常時事務不回滾
register 函數內部使用的方法是在 trait 中實現的,所有的 side 方法在出錯時都會拋出異常。 但不幸的是,當在控制器外部的一個側方法中拋出異常時(例如:findRefererIdFromRequest() 或 findRefererIdFromRequest() 或 collectDataFromRequest()),數據庫返回操作不會發生並且由 create 創建的新用戶方法仍在數據庫中,無法回滾
class RegisterController extends Controller
{
use AuthenticationTrait;
public function register(RegisterRequest $request)
{
DB::beginTransaction();
try {
# Collect data from request
$dataCollect = $this->collectDataFromRequest($request);
# Create a new user
$this->createUser($dataCollect);
# Find ReferrerID from the request by invitation code
$referrerId = $this->findRefererIdFromRequest($request);
# Put ReferrerId into the user profile
$this->putReferrerId($referrerId);
DB::commit();
# Return success response
return response()->json($this->registerSuccessResponse());
} catch (\Exception $ex) {
DB::rollBack();
return response()->json(['status' => false, 'message' => $ex->getMessage()], 422);
}
}
}
trait AuthenticationTrait
{
protected function collectDataFromRequest($request)
{
try {
return collect($request->only([
'name', 'email', 'password', 'country_id', 'language_id'
]));
} catch (\Throwable $th) {
throw new CustomException(__("The system is unable to collect input data."));
}
}
protected function createUser($dataCollect)
{
try {
# Generate hashed password
$hashedPassword = bcrypt($dataCollect->get('password'));
$dataCollect->put('password', $hashedPassword);
# Create a new user
$this->user = $this->userRepository->create($dataCollect->toArray());
} catch (\Exception $th) {
throw new CustomException(__('Sorry! The system is unable to create a new user account.'));
}
}
protected function findRefererIdFromRequest($request)
{
# I have intentionally thrown an exception
throw new CustomException(__("The invitation code is invalid."));
}
protected function putReferrerId($referrerId)
{
# Update user profile and put referrerId into the user profile
$this->user->update(['referrer_id' => $referrerId]);
}
// Other funtions ...
}
我找到了問題的答案。
仔細一看,原來數據庫引擎是默認值MyISAM,不支持事務。
為了使事務可控,必須將數據庫引擎設置為InnoDB。
轉到數據庫配置文件並將數據庫引擎更改為 InnoDB
配置/數據庫.php
'connections' => [
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
// 'engine' => "MyISAM",
'engine' => "InnoDB",
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
]
首先將您的數據庫事務放在 try 塊之外,如果 invitation_code 為真,則關於特征函數中的異常處理,只需返回它即可。 特征中是否也存在此方法“getUserIdByInvitationCode”?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.