Home
Download
Document
Q&A
Video
Donate
Source Code
Code-Galaxy
Business
Swoole Tracker
Swoole Compiler
Login
Register
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
多个模型如何进行事务异常回退?
### 问题描述 多个模型继承一个数据库基础模型。例如 users、pre_stocks、stocks。 业务层 users、pre_stocks、stocks。代码在 pre_stock和stocks写后在users业务层里调用,如果其中一个流程执行失败后要退回所有的流程。 目前测试后只有users模型会回退。 手撸了一个swoole 框架 数据库的PDO连接池 ### Swoole版本,PHP版本,以及操作系统版本信息 swoole 4.8.6 php8.0.15 ### 相关代码 ```php class Users { public $model = null; public function __construct() { $this->model = new Db(); } public function set_pre_stock(int $user_id, array $pre_stock) { if (empty($pre_stock)) { return false; } try { $this->model->startTrans(); $preStocks = (new PreStocks()); $getAll_by_user_id = $preStocks->getAll_by_user_id($user_id); $lists = []; $not_exists_list = []; if (empty($getAll_by_user_id)) { for ($i = 0; $i < count($pre_stock); $i++) { $item = $pre_stock[$i]; $lists[] = ['user_id' => $user_id, 'stock_id' => $item['id'], 'number' => $item['stock']]; } if (!$preStocks->saveAll($lists)) { throw new Exception('保存失败'); } } else { $pre_stock_key_lists = array_column($getAll_by_user_id, 'number', 'stock_id'); $stock_update_lists = []; for ($i = 0; $i < count($pre_stock); $i++) { $item = $pre_stock[$i]; if (!array_key_exists($item['id'], $pre_stock_key_lists)) { array_push($not_exists_list, ['user_id' => $user_id, 'stock_id' => $item['id'], 'number' => $item['stock']]); } else { $pre_stock_number = $pre_stock_key_lists[$item['id']]; if ($item['stock'] > $pre_stock_number) { throw new Exception('件数已超'); break; } $pre_stock_key_lists[$item['id']] = $pre_stock_number + $item['stock']; } $stock_update_lists[] = $item; } for ($i = 0; $i < count($stock_update_lists); $i++) { $item = $stock_update_lists[$i]; $stock = $pre_stock_key_lists[$item['id']]; $stock_update_lists[$i]['stock'] = $stock; } $update_stock_lists = array_column($stock_update_lists, 'stock', 'id'); for ($i = 0; $i < count($getAll_by_user_id); $i++) { $item = $getAll_by_user_id[$i]; $getAll_by_user_id[$i]['update'] = false; if (array_key_exists($item['stock_id'], $update_stock_lists)) { $getAll_by_user_id[$i]['number'] = $update_stock_lists[$item['stock_id']]; $getAll_by_user_id[$i]['update'] = true; } } if (!$preStocks->updateAll($getAll_by_user_id)) { throw new Exception('预存失败'); } if (!empty($not_exists_list)) { if (!$preStocks->saveAll($not_exists_list)) { throw new Exception('未存在的预存保存失败'); } } $stock_ids = array_column($pre_stock, 'id'); $stock_numbers=array_column($pre_stock, 'stock','id'); $stocksbus = (new Stocks()); if (!$stocksbus->stock_subtract_update($stock_ids, $stock_numbers)) { throw new Exception('库存更新失败'); } } $this->model->commit(); } catch (\Exception $e) { $this->model->rollBack(); Log::error($e->getMessage() . ' Line:' . $e->getLine()); return false; } return true; } } ``` ### 你期待的结果是什么? 只要一个出错,所有的流程都要回退
发布于11月前 · 8 次浏览 · 来自
提问
michonnehsu
### 问题描述 多个模型继承一个数据库基础模型。例如 users、pre_stocks、stocks。 业务层 users、pre_stocks、stocks。代码在 pre_stock和stocks写后在users业务层里调用,如果其中一个流程执行失败后要退回所有的流程。 目前测试后只有users模型会回退。 手撸了一个swoole 框架 数据库的PDO连接池 ### Swoole版本,PHP版本,以及操作系统版本信息 swoole 4.8.6 php8.0.15 ### 相关代码 ```php class Users { public $model = null; public function __construct() { $this->model = new Db(); } public function set_pre_stock(int $user_id, array $pre_stock) { if (empty($pre_stock)) { return false; } try { $this->model->startTrans(); $preStocks = (new PreStocks()); $getAll_by_user_id = $preStocks->getAll_by_user_id($user_id); $lists = []; $not_exists_list = []; if (empty($getAll_by_user_id)) { for ($i = 0; $i < count($pre_stock); $i++) { $item = $pre_stock[$i]; $lists[] = ['user_id' => $user_id, 'stock_id' => $item['id'], 'number' => $item['stock']]; } if (!$preStocks->saveAll($lists)) { throw new Exception('保存失败'); } } else { $pre_stock_key_lists = array_column($getAll_by_user_id, 'number', 'stock_id'); $stock_update_lists = []; for ($i = 0; $i < count($pre_stock); $i++) { $item = $pre_stock[$i]; if (!array_key_exists($item['id'], $pre_stock_key_lists)) { array_push($not_exists_list, ['user_id' => $user_id, 'stock_id' => $item['id'], 'number' => $item['stock']]); } else { $pre_stock_number = $pre_stock_key_lists[$item['id']]; if ($item['stock'] > $pre_stock_number) { throw new Exception('件数已超'); break; } $pre_stock_key_lists[$item['id']] = $pre_stock_number + $item['stock']; } $stock_update_lists[] = $item; } for ($i = 0; $i < count($stock_update_lists); $i++) { $item = $stock_update_lists[$i]; $stock = $pre_stock_key_lists[$item['id']]; $stock_update_lists[$i]['stock'] = $stock; } $update_stock_lists = array_column($stock_update_lists, 'stock', 'id'); for ($i = 0; $i < count($getAll_by_user_id); $i++) { $item = $getAll_by_user_id[$i]; $getAll_by_user_id[$i]['update'] = false; if (array_key_exists($item['stock_id'], $update_stock_lists)) { $getAll_by_user_id[$i]['number'] = $update_stock_lists[$item['stock_id']]; $getAll_by_user_id[$i]['update'] = true; } } if (!$preStocks->updateAll($getAll_by_user_id)) { throw new Exception('预存失败'); } if (!empty($not_exists_list)) { if (!$preStocks->saveAll($not_exists_list)) { throw new Exception('未存在的预存保存失败'); } } $stock_ids = array_column($pre_stock, 'id'); $stock_numbers=array_column($pre_stock, 'stock','id'); $stocksbus = (new Stocks()); if (!$stocksbus->stock_subtract_update($stock_ids, $stock_numbers)) { throw new Exception('库存更新失败'); } } $this->model->commit(); } catch (\Exception $e) { $this->model->rollBack(); Log::error($e->getMessage() . ' Line:' . $e->getLine()); return false; } return true; } } ``` ### 你期待的结果是什么? 只要一个出错,所有的流程都要回退
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
还没有评论!
微信公众号
热门内容
- 重启worker时希望读取到其它文件的配置变更
- Think-Swoole: 全面协程化你的 ThinkPHP 应用
- 协程Co::set设置hook_flage失效
- fatal error: 'pcre2.h' file not found
- 环境有http2,调用就报错
- 最新版的协程 Redis 客户端 已不建议使用,那Redis服务端以后还会存在吗?
- framework 404
- Swoole-Cli v5.0.2 增加 opcache/readline 扩展,强化 Cli-Server
- 用curl后,php代码处理的很快,但是返回的给前端的时间慢,有人知道原因吗
- Swoole-cli 5.0 Window10运行Hyperf命令行报错
作者其它话题
- mysql的锁会影响到协程吗?
- 关于发送 Ping 帧的疑惑
- 关于服务端(异步风格)的bind疑问
- 关于 TCP客户端案例的疑惑
- 关于Worker进程的疑惑
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 请问那个一键协程化的代码是放外面还是set里面
- 多个模型如何进行事务异常回退?
- websocket开启wss报错