事务处理代码复用咨询:避免代码重复的设计模式
解决方案:闭包封装事务逻辑 / 模板方法模式
你的场景核心是固定事务流程 + 可变业务逻辑,以下两种方案可以彻底消除代码重复:
方案1:PHP闭包封装通用事务处理器(Laravel环境下最便捷)
利用PHP闭包把固定的事务代码抽成通用方法,业务逻辑以闭包形式传入,实现复用:
第一步:封装通用事务方法
在工具类或Service层新增通用处理方法:
/** * 带事务的业务执行器 * @param \Closure $businessLogic 待执行的业务逻辑 * @param string $successMsg 成功提示文本 * @return array 执行结果 */ public function runInTransaction(\Closure $businessLogic, string $successMsg) { try { DB::beginTransaction(); // 执行传入的自定义业务逻辑 $businessLogic(); DB::commit(); return ['msg' => $successMsg]; } catch (\Throwable $error) { DB::rollBack(); return ['msg' => $error->getMessage()]; } }
第二步:简化业务方法
原createGroupWith可以精简为只保留业务逻辑:
public function createGroupWith($data) { return $this->runInTransaction(function () use ($data) { $modules_id = array_pop($data); $group = Group::create($data); $group->modules()->attach($modules_id); }, trans('cms.groups.success_create')); }
后续所有需要事务的业务方法,都只需传入对应的业务闭包和成功提示,完全复用事务的开启、提交、回滚逻辑。
方案2:模板方法模式(适合复杂标准化流程)
如果项目中有大量标准化事务场景,需要统一约束流程步骤,可使用模板方法模式:
第一步:定义抽象基类
abstract class TransactionalService { public function execute(string $successMsg) { try { DB::beginTransaction(); // 调用子类实现的业务逻辑 $this->handleBusiness(); DB::commit(); return ['msg' => $successMsg]; } catch (\Throwable $error) { DB::rollBack(); return ['msg' => $error->getMessage()]; } } // 子类必须实现的业务逻辑方法 abstract protected function handleBusiness(); }
第二步:子类实现具体业务
class GroupService extends TransactionalService { private $data; public function __construct($data) { $this->data = $data; } protected function handleBusiness() { $modules_id = array_pop($this->data); $group = Group::create($this->data); $group->modules()->attach($modules_id); } }
第三步:业务调用
public function createGroupWith($data) { $service = new GroupService($data); return $service->execute(trans('cms.groups.success_create')); }
这种方式适合业务逻辑复杂、需要统一管控流程的场景,但相比闭包写法会增加类的定义,可根据项目复杂度选择。
总结
- Laravel项目优先选闭包方案:轻量快捷,代码复用性高,无需额外定义大量类;
- 大型标准化项目选模板方法模式:通过抽象类统一约束流程,便于长期维护。
内容的提问来源于stack exchange,提问作者Bernardo Benini Fantin
相关产品推荐
相关产品推荐

