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

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

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

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

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

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

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

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《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年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!