如何在PHP中避免日志重复记录‘Cancellation Identified’
Let's break down your problem and fix that duplicate "Cancellation Identified" logging issue step by step.
First, let's pinpoint why the log is repeating 3 times during a single code run:
- Looking at your existing code, when you detect a contract isn't in the
ContractCancellationtable, you only mark the contract ascancel_pendingbut never add a record to theContractCancellationtable itself. This means every time the code runs, it will keep hitting that same conditional branch and logging the message again. - If
process_imports()runs in a loop, the same contract might be processed multiple times in the same execution cycle, even if database checks are in place.
Here are two targeted PHP fixes to resolve this:
Fix 1: Root Cause Solution (Database Record)
This is the most permanent fix—we'll add a ContractCancellation record when we first identify the cancellation, so future runs won't re-trigger the log:
if(!empty($contract)){ // 根据取消日期判断合同是否已取消 if ((isset($data['cancelled_date'])) && (substr_count($data['sold_date'], '/') == 2) && ($contract->cancelled_date >= '2015-01-01')) { // 通过已取消合同表判断该取消是否为新记录 $IsCancelled = ContractCancellation::LocateCancellation($contract->moxy_contract_id); if (!$IsCancelled->first()) { // 合同未在取消表中,标记为待处理取消状态 $contract->cancel_pending = 1; if($contract->hold == '1'){ LogAction::add("Data Adjustment", "Hold Removed Due To Contract Being Cancelled.", 0, "", $contract->moxy_contract_id); } $contract->hold = 0; $contract->save(); // 记录取消日志(仅执行一次) LogAction::add("Data Adjustment", "Cancellation Identified.", 0, "", $contract->moxy_contract_id); // 关键:添加记录到取消表,避免后续重复处理 ContractCancellation::create([ 'moxy_contract_id' => $contract->moxy_contract_id, 'cancelled_date' => $data['cancelled_date'], // 根据你的模型字段调整 // 可添加其他必要字段,比如创建时间、操作人ID等 ]); } } $contract->cancel_miles = !empty($data['cancel_miles']) ? $data['cancel_miles'] : 0; $contract->cancel_reason = !empty($data['cancel_reason']) ? $data['cancel_reason'] : NULL; $contract->save(); }
Fix 2: In-Memory Tracking (Same Execution Cycle)
If you can't modify the ContractCancellation write logic right now, this fix uses a static array to track which contracts have already been logged during the current code run:
// 在process_imports()函数开头或合适的作用域内初始化静态跟踪数组 static $loggedCancellationIds = []; if(!empty($contract)){ // 根据取消日期判断合同是否已取消 if ((isset($data['cancelled_date'])) && (substr_count($data['sold_date'], '/') == 2) && ($contract->cancelled_date >= '2015-01-01')) { // 通过已取消合同表判断该取消是否为新记录 $IsCancelled = ContractCancellation::LocateCancellation($contract->moxy_contract_id); if (!$IsCancelled->first()) { // 合同未在取消表中,标记为待处理取消状态 $contract->cancel_pending = 1; if($contract->hold == '1'){ LogAction::add("Data Adjustment", "Hold Removed Due To Contract Being Cancelled.", 0, "", $contract->moxy_contract_id); } $contract->hold = 0; $contract->save(); // 检查是否已记录过该合同的取消日志,避免同一运行周期内重复 if (!in_array($contract->moxy_contract_id, $loggedCancellationIds)) { LogAction::add("Data Adjustment", "Cancellation Identified.", 0, "", $contract->moxy_contract_id); $loggedCancellationIds[] = $contract->moxy_contract_id; } } } $contract->cancel_miles = !empty($data['cancel_miles']) ? $data['cancel_miles'] : 0; $contract->cancel_reason = !empty($data['cancel_reason']) ? $data['cancel_reason'] : NULL; $contract->save(); }
The pseudocode you shared (if($searchfor) { $searchfor = "Cancellation Identified"; $searchfor = true; continue process_imports(); }) aligns with Fix 2's logic—marking a processed item to skip future logging in the same run. The static array implementation is the PHP version of that idea.
内容的提问来源于stack exchange,提问作者user11820588

