fastadmin 事务操作异常抛出 $this->error($e->getMessage());

遇到一个代码异常,事务操作明明都全部成功处理了,却还是进入了catch
代码如下
// 开始事务(Db类统一事务)
        Db::startTrans();
        try {
            // 生成订单号:日期(8位) + 时间(6位) + 随机数(4位)
            $orderNo = date('Ymd') . date('His') . mt_rand(1000, 9999);

            // 1. 插入挂号信息(使用空合并运算符增强健壮性)
            $orderData = [
                'order_on'   => $orderNo,
                'name'       => $params['name'],
                'sex'        => $params['sex'],
                'phone'      => $params['phone'],
                'desc'       => $params['desc'] ?? '',      // 健壮性增强:避免未定义索引
                'doctor'     => $params['doctor'],
                'type'       => $params['type'] ?? '',      // 健壮性增强
                'amount'     => $params['amount'],
                'yytime'     => $params['yytime'],
                'slot'       => $params['slot'],
                'hos_name'   => $params['hos_name'] ?? '',  // 健壮性增强
                'createtime' => time()
            ];
            $insertResult = Db::name($orderTable)->insert($orderData);
            if (!$insertResult) {
                throw new \Exception('挂号信息插入失败');
            }

            // 2. 更新号源数量(使用原子操作,避免并发超卖)
            $scheduleTable = 'xcx_schedule';  // 根据实际表名调整,原模型对应 xcx_schedule
            $schedule = Db::name($scheduleTable)
                ->where('id', $params['schedule_id'])
                ->lock(true)  // 加行锁,防止并发问题(需要 InnoDB)
                ->find();

            if (!$schedule) {
                throw new \Exception('排班信息不存在');
            }
            if ($schedule['remaining_slots'] <= 0) {
                throw new \Exception('号源已用完');
            }

            // 执行减号源操作(条件更新确保剩余号源>0)
            $affected = Db::name($scheduleTable)
                ->where('id', $params['schedule_id'])
                ->where('remaining_slots', '>', 0)
                ->setDec('remaining_slots', 1);

            if ($affected === false) {
                throw new \Exception('号源更新失败');
            }
            if ($affected == 0) {
                throw new \Exception('号源已被抢完,请刷新后重试');
            }

            // 提交事务
            Db::commit();
            $this->success('提交成功');
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            // $this->error('异常信息:' . $e->getMessage() . ',文件:' . $e->getFile() . ',行:' . $e->getLine());
            $this->error("操作失败:" . $e->getMessage());
        }

操作都成功了,后台也正常添加了数据,返回数据还是

$this->error("操作失败:" . $e->getMessage());里面的
问题出在 $this->success() api的success方法调用了此类HttpResponseException,而 catch 块会捕获该异常,导致执行 $this->error(),覆盖了原本的成功响应。所以可以把$this->success('提交成功');放到事务外部响应

image

 还有一种办法就是在事务中 return [ 'code'=>1 ,'msg'=>'提交成功'];  这样也可以, 但是这样更麻烦

 

 

posted @ 2026-04-20 15:03  冷晨  阅读(12)  评论(0)    收藏  举报