You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP多重foreach循环数组赋值异常:仅首个元素生效问题排查

问题分析与解决方案

你的代码出现问题的核心原因有两个:


1. 不匹配的$ready元素会覆盖已设置的属性

在你的内层foreach循环中,每一次遇到不匹配$gi->id的$rdy元素时,都会执行else分支,把$gi的属性重置为空。

比如处理$data['garduinduk'][0](id=1)时:

  • 第一次循环匹配$ready[0](lokasi=1),给$gi赋值了ON PROGRESS相关属性;
  • 但后面三次循环的$rdy元素(lokasi=16、2、2)都不匹配id=1,每次都会执行else把属性清空;
  • 最终$gi的属性会变成最后一次循环的结果——空值,这显然和你的预期不符。

2. 多个匹配项时,后续项会覆盖之前的赋值

对于有多个匹配$gi->id的$rdy元素(比如$data['garduinduk'][1]的id=2,对应$ready[2]和$ready[3]),你的代码会用最后一个匹配的元素覆盖之前的赋值。如果你的需求是优先显示On_progress状态,这种逻辑会导致优先级更高的状态被覆盖。


修正后的代码

我调整了逻辑,先给$gi设置默认空值,然后遍历$ready找匹配项,找到后赋值,并且如果是On_progress状态就直接跳出循环(保证优先级),去掉了会重置属性的else分支:

foreach ($data['garduinduk'] as $key => $gi){ 
    // 先设置默认值,避免未找到匹配项时属性未定义
    $gi->berlaku_dari = ''; 
    $gi->berlaku_sampai = ''; 
    $gi->file = ''; 

    foreach ($ready as $rdy){ 
        if ($rdy->lokasi == $gi->id){ 
            if ($rdy->status == 'On_progress'){ 
                $gi->berlaku_dari = 'ON PROGRESS'; 
                $gi->berlaku_sampai = 'ON PROGRESS'; 
                $gi->file = 'ON PROGRESS'; 
                // 找到On_progress状态就跳出,避免被后续的Selesai项覆盖
                break;
            }else{ 
                $gi->berlaku_dari = $rdy->berlaku_dari; 
                $gi->berlaku_sampai = $rdy->berlaku_sampai; 
                $gi->file = $rdy->file; 
                // 如果需要保留最新的Selesai记录,可以去掉上面的break,让最后一个匹配项生效
            } 
        } 
        // 移除else分支,避免不匹配时清空已设置的属性
    } 
}

额外优化建议

如果$ready数组的数据量较大,这种嵌套循环的效率会很低。你可以先把$ready数组转换成以lokasi为键的关联数组,这样可以直接通过$gi->id查找匹配项,时间复杂度从O(n*m)降到O(n+m):

// 先预处理$ready,按lokasi分组,保留On_progress优先的项
$readyMap = [];
foreach ($ready as $rdy) {
    $lokasi = $rdy->lokasi;
    // 如果当前lokasi还没记录,或者已有记录不是On_progress,就更新
    if (!isset($readyMap[$lokasi]) || $readyMap[$lokasi]->status != 'On_progress') {
        if ($rdy->status == 'On_progress') {
            $readyMap[$lokasi] = $rdy;
        } else {
            // 如果是Selesai,只有当没有On_progress时才保留
            if (!isset($readyMap[$lokasi])) {
                $readyMap[$lokasi] = $rdy;
            }
        }
    }
}

// 然后遍历garduinduk直接取值
foreach ($data['garduinduk'] as $gi) {
    $gi->berlaku_dari = '';
    $gi->berlaku_sampai = '';
    $gi->file = '';

    if (isset($readyMap[$gi->id])) {
        $rdy = $readyMap[$gi->id];
        if ($rdy->status == 'On_progress') {
            $gi->berlaku_dari = 'ON PROGRESS';
            $gi->berlaku_sampai = 'ON PROGRESS';
            $gi->file = 'ON PROGRESS';
        } else {
            $gi->berlaku_dari = $rdy->berlaku_dari;
            $gi->berlaku_sampai = $rdy->berlaku_sampai;
            $gi->file = $rdy->file;
        }
    }
}

这种方式不仅效率更高,逻辑也更清晰,更容易维护。

内容的提问来源于stack exchange,提问作者highcal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:59:10