PHP遍历物流跟踪事件时如何正确设置进度条进度值
问题场景
现有一组按时间从新到旧排序的物流跟踪数组,结构如下:
Array ( [0] => stdClass Object ( [message] => Out for delivery [date] => 07/06/2022 [time] => 10:30:12 AM ) [1] => stdClass Object ( [message] => Consolidation arrived at gateway [date] => 07/06/2022 [time] => 8:00:07 AM ) [2] => stdClass Object ( [message] => Departed sort facility [date] => 07/06/2022 [time] => 6:30:07 AM ) [3] => stdClass Object ( [message] => Arrived at sort facility [date] => 07/06/2022 [time] => 12:15:05 AM ) [4] => stdClass Object ( [message] => Departed sort facility [date] => 06/06/2022 [time] => 10:00:06 PM ) [5] => stdClass Object ( [message] => Driver collected [date] => 06/06/2022 [time] => 4:45:07 PM ) [6] => stdClass Object ( [message] => Label created [date] => 06/06/2022 [time] => 12:52:27 PM ) )
预先定义了进度条变量:
$progress = '0.25';
需求是根据数组中存在的物流节点,给进度条设置对应进度值。原有代码遍历数组时,多个匹配到的节点会反复覆盖$progress的值,最终结果不符合预期,原代码如下:
foreach($events as $item) { if ($item->message == "POD"){ $progress = '1'; } if ($item->message == "Out for delivery"){ $progress = '0.75'; } if ($item->message == "Departed sort facility"){ $progress = '0.5'; } if ($item->message == "Driver collected"){ $progress = '0.25'; } }
问题原因
- 物流数组默认按最新事件在前、最早事件在后排序,遍历过程中先匹配到高进度节点后,会继续被后面更早的低进度节点覆盖,最终拿到的是最早匹配到的低进度值
- 所有判断条件独立执行,没有做进度值的大小比较,也没有匹配到最高优先级节点后的终止逻辑,导致无意义的重复赋值。
修复方案
方案1:映射表+取最大值(推荐,稳定性高)
提前定义节点和进度值的映射关系,遍历过程中只保留匹配到的最高进度值,不依赖数组排序规则:
// 节点-进度映射表,进度值随物流推进升高 $progressMap = [ 'Driver collected' => 0.25, 'Departed sort facility' => 0.5, 'Out for delivery' => 0.75, 'POD' => 1 ]; $progress = 0; foreach($events as $item) { $currentMsg = $item->message; // 仅当当前节点在映射表中、且对应进度高于已记录值时才更新 if (isset($progressMap[$currentMsg]) && $progressMap[$currentMsg] > $progress) { $progress = $progressMap[$currentMsg]; } }
按照给出的示例数组,最终$progress会取到最高值0.75,符合物流已经到派送环节的实际状态。
方案2:按优先级匹配+终止遍历(性能更高)
利用数组最新事件在前的排序规则,遍历判断时从最高进度节点开始匹配,匹配到即终止循环,不需要遍历全部节点:
$progress = 0; foreach($events as $item) { if ($item->message == "POD"){ $progress = 1; break; } if ($item->message == "Out for delivery"){ $progress = 0.75; break; } if ($item->message == "Departed sort facility"){ $progress = 0.5; break; } if ($item->message == "Driver collected"){ $progress = 0.25; break; } }
注意:该方案强依赖数组的排序规则,如果后续物流接口返回的事件顺序变为最早在前、最新在后,会直接取到最低进度值,使用前需要确认数组排序逻辑固定。
内容的提问来源于stack exchange,提问作者idwes7
相关产品推荐
相关产品推荐

