请问使用 Laravel 模型观察者时,如何配合使用事务

我使用模型的观察者,其中的的删除事件,大部分用来作用在删除与当前数据有关联的数据,例如:

  1. 删除商品时,需要将商品下的图片删除,两张表,那么会在 deleted 事件内删除掉商品图片表内对应的数据
  2. 角色删除时,需要解除角色的所有节点数据之间的关联。使用多对多的 detach 方法

多表同时删除数据,就会涉及到事务操作,想请问大家,如何在观察者模式内使用事务,在其遇到错误时进行回滚操作。
我目前试过的方法是在 deleting 开启事务,deleted 的末尾提交事务,但是并不会 rollback,因为我没办法在代码内写 try catch,因为我的控制器内有删除语句,deleted 内也有删除语句
以下分别是控制器删除方法代码观察者类代码最终运行的 sql 语句
控制器删除方法代码观察者类代码最终运行的sql语句

我试着在控制器内使用 DB::transaction 包裹我的删除语句,observer 类里只留下 deleted 方法并且不使用 DB 门面,最后运行的 sql 语句和图三是一致的,这样可以达到目的,但是这样看起来很笨,因为这就代表了我在书写控制器代码时我是一定知道了其他地方有联动删除,这并不符合代码的 SOLID 原则。

想请问一下大家是怎么解决这个问题的,还是说我的应用方法本身就是有问题的,观察者不应该用来删除其他相关联的数据

最后有一个另外小小的疑惑,我总是在各种文献里看到 laravel 的 DB::transaction 方法可以在数据库操作遇到异常时自动回滚,请问有办法可以模拟 laravel 操作数据库时遇到问题这种操作吗

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

1 事务的使用, 看业务啊

比如:

a. 一个控制器内的一个方法, 业务上要求整个请求链路下, 保持数据一致,那就在控制器层, 包裹 try/catch 事务!

b. 一个控制器内调用了多个服务, 例如 serviceA (订单流程, 关键业务), serviceB (送积分流程, 非关键业务) 等等; 业务只要求关键业务 serviceA (订单流程), 数据保持强一致, 那就只在 serviceA 处包裹 try/catch 事务!

2 如何模拟数据库操作遇到异常时自动回滚

我是这么干的,随便哪个都行:

a. 代码里任意处, throw new Exception (...), 模拟异常; 记得打上 TODO DEBUG, 别误上生产环境, 别回来找我算账 :joy:

b. 关闭本地 mysql 服务;(mysql 服务若是 dev 环境公用, 不可关闭的话, 直接修改本地项目中.env 中数据库配置文件, 比如:账号密码 IP 等等)

4年前 评论
eiixy 4年前
Siam (楼主) 4年前
Siam (楼主) 4年前
eiixy 4年前
user02 4年前
Siam (楼主) 4年前
讨论数量: 15
sunxyw

第一个问题我不会。

这二个问题文档中有提到如何手动使用事务,就是在 DB::beginTransaction();DB::commit() 中间加上 DB::rollback() 就会进行回滚。

4年前 评论
Siam (楼主) 4年前

1 事务的使用, 看业务啊

比如:

a. 一个控制器内的一个方法, 业务上要求整个请求链路下, 保持数据一致,那就在控制器层, 包裹 try/catch 事务!

b. 一个控制器内调用了多个服务, 例如 serviceA (订单流程, 关键业务), serviceB (送积分流程, 非关键业务) 等等; 业务只要求关键业务 serviceA (订单流程), 数据保持强一致, 那就只在 serviceA 处包裹 try/catch 事务!

2 如何模拟数据库操作遇到异常时自动回滚

我是这么干的,随便哪个都行:

a. 代码里任意处, throw new Exception (...), 模拟异常; 记得打上 TODO DEBUG, 别误上生产环境, 别回来找我算账 :joy:

b. 关闭本地 mysql 服务;(mysql 服务若是 dev 环境公用, 不可关闭的话, 直接修改本地项目中.env 中数据库配置文件, 比如:账号密码 IP 等等)

4年前 评论
eiixy 4年前
Siam (楼主) 4年前
Siam (楼主) 4年前
eiixy 4年前
user02 4年前
Siam (楼主) 4年前

请问楼主最后是怎么解决的?

4年前 评论
Siam (楼主) 4年前

全局捕获,具体呢?我也遇到这样的问题了,怎么全局捕获呢,哥们!观察者操作了,结果事务回滚,凉凉。你还有其他方案不!分享一下,万分感谢。

2年前 评论
Siam (楼主) 2年前

在 Handler.php 捕获 QueryException,进行 rollback

没弄懂怎么处理,楼主要有示例贴一份就好了

2年前 评论
Siam (楼主) 2年前