请问使用 Laravel 模型观察者时,如何配合使用事务
我使用模型的观察者,其中的的删除事件,大部分用来作用在删除与当前数据有关联的数据,例如:
- 删除商品时,需要将商品下的图片删除,两张表,那么会在deleted事件内删除掉商品图片表内对应的数据
- 角色删除时,需要解除角色的所有节点数据之间的关联。使用多对多的detach方法
多表同时删除数据,就会涉及到事务操作,想请问大家,如何在观察者模式内使用事务,在其遇到错误时进行回滚操作。
我目前试过的方法是在deleting开启事务,deleted的末尾提交事务,但是并不会rollback,因为我没办法在代码内写try catch,因为我的控制器内有删除语句,deleted内也有删除语句
以下分别是控制器删除方法代码、观察者类代码、最终运行的sql语句
我试着在控制器内使用 DB::transaction 包裹我的删除语句,observer类里只留下deleted方法并且不使用DB门面,最后运行的sql语句和图三是一致的,这样可以达到目的,但是这样看起来很笨,因为这就代表了我在书写控制器代码时我是一定知道了其他地方有联动删除,这并不符合代码的 SOLID 原则。
想请问一下大家是怎么解决这个问题的,还是说我的应用方法本身就是有问题的,观察者不应该用来删除其他相关联的数据
最后有一个另外小小的疑惑,我总是在各种文献里看到laravel的DB::transaction方法可以在数据库操作遇到异常时自动回滚,请问有办法可以模拟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 等等)