遵循Repository/Service模式时INSERT重复四次的逻辑排查求助
问题根源分析与修复方案
核心问题:Service层重复执行插入操作
你的EstoqueService::insertEstoque方法存在明显逻辑错误,直接导致单次请求执行两次插入:
public function insertEstoque() { $db = new MySQL(); $insert = new EstoqueRepositories($db); // 第一次执行INSERT if(!empty($insert->inserirEstoque($_POST))){ // 第二次执行INSERT return $insert->inserirEstoque($_POST); } else { return false; } }
- 条件判断里的
$insert->inserirEstoque($_POST)已经完成一次数据库插入 - 若插入成功,return语句会再次调用该方法,触发第二次插入
如果控制器的insert方法被额外触发一次(比如用户重复点击提交按钮、跳转失败后刷新页面),两次请求×两次插入,就会出现四次数据。
修复步骤
1. 修复Service层重复调用问题
将仓库方法的执行结果存入变量,避免重复执行:
public function insertEstoque() { $db = new MySQL(); $insert = new EstoqueRepositories($db); // 仅执行一次插入,存储结果 $insertResult = $insert->inserirEstoque($_POST); // 直接返回布尔结果即可,无需二次判断empty return $insertResult; }
2. 避免控制器重复触发
- 确保
header('Location: ../../index.php')前无任何输出(包括PHP标签外的空格、echo内容),可添加exit终止后续代码执行:
public function insert() { $insert = new EstoqueService(); $insert->insertEstoque(); header('Location: ../../index.php'); exit; // 阻止跳转后代码继续执行 }
- 前端添加防重复提交逻辑(比如点击提交后禁用按钮)
贴合SOLID架构的优化建议
- 依赖注入:Service层不要在方法内实例化依赖,通过构造函数注入,符合依赖倒置原则:
class EstoqueService { private $estoqueRepo; public function __construct(EstoqueRepositories $estoqueRepo) { $this->estoqueRepo = $estoqueRepo; } public function insertEstoque(array $dadosPost) { return $this->estoqueRepo->inserirEstoque($dadosPost); } }
- 避免全局变量依赖:不要在Service层直接使用
$_POST,改为参数传入,提升方法可控性与可测试性:
// 控制器调用 public function insert() { $db = new MySQL(); $repo = new EstoqueRepositories($db); $insertService = new EstoqueService($repo); $insertService->insertEstoque($_POST); header('Location: ../../index.php'); exit; }
内容的提问来源于stack exchange,提问作者Eder
相关产品推荐
相关产品推荐

