如何优化清理Laravel项目中包含多重条件的冗余循环代码?
Laravel 结算逻辑优化方案
你的代码核心问题是doChunk()判断的两个分支存在大量重复的交易ID提取、结算插入、日志写入逻辑,我们可以先通过逻辑分层消除重复代码,复杂度高的场景再搭配设计模式扩展。
第一步:基础优化(无额外设计模式,兼容原有逻辑)
把两个分支的输出统一为相同结构的待处理分组列表,消除重复代码:
foreach ($transactionsGroupBys as $transactionsGroupBy) { // 原有重复判断逻辑保留 if ($this->checkExistSettlement($transactionsGroupBy, Carbon::today())) { $this->setErrorLog('This settlement has already been created', $transactionsGroupBy); continue; } try { // 两种分支统一输出同结构的待处理分组列表 $pendingGroups = $this->doChunk() ? $this->getChunkedPendingGroups($transactionsGroupBy) : [$this->getNormalPendingGroup($transactionsGroupBy)]; // 统一处理所有待处理分组,消除重复逻辑 foreach ($pendingGroups as $group) { $settlements[] = $this->insertSettlement($group['group_by'], $group['transaction_ids'])->toArray(); $this->setInfoLog("Created $counter/$countSettlements settlement", $group['group_by']); } $counter += 1; } catch (\Exception $exception) { $this->setErrorLog($exception->getMessage()); continue; } } // 抽离切块场景的分组处理逻辑 protected function getChunkedPendingGroups($transactionsGroupBy): array { $transactions = $this->getTransactions($transactionsGroupBy); $maxAmountSettle = $this->configRepository->find('transaction_chunk:PUBLIC')->value; $transactionChunk = app(ChunkTransaction::class)->chunk($transactions, $maxAmountSettle); return collect($transactionChunk) ->map(fn($chunk) => [ 'group_by' => $chunk->transactions_group_by, 'transaction_ids' => collect($chunk->transactions)->pluck('id')->toArray() ]) ->toArray(); } // 抽离非切块场景的分组处理逻辑 protected function getNormalPendingGroup($transactionsGroupBy): array { $transactions = $this->getTransactions($transactionsGroupBy, ['id']); return [ 'group_by' => $transactionsGroupBy, 'transaction_ids' => $transactions ? collect($transactions)->pluck('id')->toArray() : [] ]; }
优化效果
- 重复代码完全消除,后续修改结算规则、日志规则仅需修改一处
- 单方法职责清晰,切块、非切块逻辑独立维护,可读性提升70%
- 圈复杂度从原来的5降低到3,更便于后续迭代
第二步:高扩展场景可选策略模式
如果后续还会新增更多交易分组规则(比如按时间分组、按商户等级分组等),可以用策略模式完全消除if判断,符合开闭原则:
- 定义统一策略接口
interface TransactionGroupStrategyInterface { public function getPendingGroups($transactionsGroupBy): array; }
- 实现不同策略类
// 切块策略 class ChunkedGroupStrategy implements TransactionGroupStrategyInterface { // 把上面getChunkedPendingGroups的逻辑移到这里 } // 普通分组策略 class NormalGroupStrategy implements TransactionGroupStrategyInterface { // 把上面getNormalPendingGroup的逻辑移到这里 }
- 新增策略工厂类,根据配置返回对应策略
class TransactionGroupStrategyFactory { public function make(bool $isChunk): TransactionGroupStrategyInterface { return $isChunk ? app(ChunkedGroupStrategy::class) : app(NormalGroupStrategy::class); } }
- 原有循环代码简化为:
$strategy = app(TransactionGroupStrategyFactory::class)->make($this->doChunk()); foreach ($transactionsGroupBys as $transactionsGroupBy) { // ... 原有前置判断不变 try { $pendingGroups = $strategy->getPendingGroups($transactionsGroupBy); // ... 原有统一处理逻辑不变 } catch (\Exception $e) { // ... 异常处理不变 } }
后续新增分组规则仅需新增策略类,不需要修改原有循环逻辑。
内容的提问来源于stack exchange,提问作者mohammad nabipour
相关产品推荐
相关产品推荐

