#事务回滚的回调函数
##在usercontroller里面写一个方法
1.防止出现异常而导致数据不完整性调用TransactionService这个控制器里面的handle方法
TransactionService::handle(function () use ($data) {
foreach ($data as $item) {
ProgramLabelService::edit(['weight' => $item['weight']], $item['program_label_id']);
}
});
2.接下来我们去TransactionService看看怎么处理 注意 Closure一定写上去
static public function handle(Closure $handle) {
DB::beginTransaction();
$result = null;
try {
$result = $handle();
DB::commit();
} catch (Exception $exception) {
DB::rollBack();
throw $exception;
}
return $result;
}
3.把函数当作参数传递到这方法里面用$handle接收,这里面的方法从头运行一直运行到赋值的地方$result = $handle();
才开始运行传递过来的方法
复杂的匿名函数
1.在提交的方法里面调用distributedLockTemplate一直运行到调用的地方然后相当于把这一块代码放到distributedLockTemplate方法去运行
到哪里开始运行就看接参数的位置在哪里
2.运行的顺序 先在submit里面运行一直运行到开始调用的地方然后去到distributedLockTemplate方法,方法从头开始运行一直运行到出参数的位置
开始运行调用的代码
public function submit(Request $request)
{
$request->validate([
'resource_id' => 'required',
'activity_id' => 'required',
'order_detail_id' => 'required',
]);
$all = $request->all();
RedisService::distributedLockTemplate("tongKeYiGouSubmit:{$all['order_detail_id']}", function () use ($all) {
$orderDetail = OrderDetailService::getByPrimaryKeyOfUser($all['order_detail_id']);
$resource = ResourceModel::query()->find($all['resource_id']);
if ($resource->type != ResourceService::TYPE_TON_KE_YI_GOU) throw new BusinessException('资源类型错误');
// 查询是否存在
$tongKeYiGou = TongKeYiGouService::get([
'resource_id' => $all['resource_id'],
'activity_id' => $all['activity_id'],
'order_detail_id' => $all['order_detail_id']
]);
if ($tongKeYiGou) {
// 存在则更新
TongKeYiGouService::edit($all, $tongKeYiGou->tong_ke_yi_gou_id);
} else {
TransactionService::handle(function () use ($all, $orderDetail) {
// 不存在则创建
TongKeYiGouService::create($all);
// 更新进度
RecordStudyProgressService::record($orderDetail, 100, $all['resource_id'], $all['activity_id']);
});
}
});
return $this->success();
}
————————
在RedisService里面
static public function distributedLockTemplate(string $key, Closure $handle, $type = self::LOCK_TYPE_THROW_EXCEPTION)
{
// 锁有效时长
$time = 5;
// 存入随机数,防止业务代码超时释放锁出错
$random = GUIDService::getGuid();
// 获取锁
$count = self::setExNx($key, $random, $time);
// 记录返回值
$result = null;
// 如果获取到锁
if ($count) {
// 执行业务代码
try {
//这里开始运行调过来的代码
$result = $handle();
} catch (Exception $exception) {
throw $exception;
} finally {
self::releaseLock($key, $random);
}
} else {
if ($type == self::LOCK_TYPE_THROW_EXCEPTION) {
throw new BusinessException('操作太快,请稍后重试');
} else if ($type == self::LOCK_TYPE_RECURSION) {
sleep(0.2);
// 递归调用
$result = self::distributedLockTemplate($key, $handle, $type);
} else {
throw new BusinessException('参数错误');
}
}
return $result;
}