PHP数组部分值被覆盖求助:MySQL关联查询后数据处理异常
问题分析与解决方案
我一眼就看出问题所在了——你在分组数组里用转录者的姓名反转+ID作为唯一键,但同一转录者的多条证书记录会共享这个键,导致后面的记录直接覆盖前面的。而你只在certId1和3的组合中发现问题,是因为这两个证书都被分到了cet分组里;如果是certId2和5的组合(都在tta分组),也会出现同样的覆盖问题,只是你没测试到而已。不同分组的证书(比如2和4)因为存在于不同的数组中,所以不会互相覆盖,这才让你误以为其他组合没问题。
下面给你两种针对性的解决方案,你可以根据业务需求选择:
方案一:按转录者聚合证书(适合展示每个转录者所有证书的场景)
这种方案会让每个转录者在对应分组下成为一个数组,里面包含他的所有证书记录,从根本上避免覆盖问题:
$list = $this->MTranscriber->getTranscribersAndTheirCertificationsList(); $data['cetlist'] = ['tta' => [], 'cet' => []]; // 先初始化分组数组 foreach ($list as $t) { // 生成转录者唯一键 $keyParts = explode(' ', trim($t['name'])); $keyParts = preg_replace('/[()]/','', $keyParts); $keyParts = array_reverse($keyParts); $key = implode(' ', $keyParts) . $t['id']; // 处理证书显示文本 $t['cet'] = $t['certName'] . ($t['regNum'] ? '-' . $t['regNum'] : ''); // 根据certId分组,确保每个键对应的是数组,再添加记录 if ($t['certId'] == 2 || $t['certId'] == 5) { if (!isset($data['cetlist']['tta'][$key])) { $data['cetlist']['tta'][$key] = []; } $data['cetlist']['tta'][$key][] = $t; } else { if (!isset($data['cetlist']['cet'][$key])) { $data['cetlist']['cet'][$key] = []; } $data['cetlist']['cet'][$key][] = $t; } } // 排序分组 if (!empty($data['cetlist']['cet'])) { ksort($data['cetlist']['cet']); } if (!empty($data['cetlist']['tta'])) { ksort($data['cetlist']['tta']); }
处理后,比如John Doe的两条证书会存在$data['cetlist']['cet']['Doe John9']数组里,包含两条完整的证书记录,不会被覆盖。
方案二:每个证书作为独立条目(适合单独展示每条证书的场景)
如果希望每条证书都是分组数组里的独立条目,只需要在生成键的时候加上certId,保证每个证书的键唯一即可:
$list = $this->MTranscriber->getTranscribersAndTheirCertificationsList(); $data['cetlist'] = ['tta' => [], 'cet' => []]; foreach ($list as $t) { // 生成包含certId的唯一键,确保每条证书都有独立键 $keyParts = explode(' ', trim($t['name'])); $keyParts = preg_replace('/[()]/','', $keyParts); $keyParts = array_reverse($keyParts); $key = implode(' ', $keyParts) . $t['id'] . '-' . $t['certId']; $t['cet'] = $t['certName'] . ($t['regNum'] ? '-' . $t['regNum'] : ''); if ($t['certId'] == 2 || $t['certId'] == 5) { $data['cetlist']['tta'][$key] = $t; } else { $data['cetlist']['cet'][$key] = $t; } } // 排序分组 if (!empty($data['cetlist']['cet'])) { ksort($data['cetlist']['cet']); } if (!empty($data['cetlist']['tta'])) { ksort($data['cetlist']['tta']); }
这种情况下,John Doe的两条证书会对应两个独立键:Doe John9-1和Doe John9-3,各自保存一条记录,不会互相覆盖。
为什么之前的array_push/array_merge没生效?
你之前尝试的array_push或array_merge没达到预期,大概率是因为没有先初始化对应键的数组。比如直接对$data['cetlist']['cet'][$key]用array_push时,这个键还不存在,PHP会把它当成null,无法执行push操作。必须先确保键对应的是一个空数组,再往里添加元素才行。
内容的提问来源于stack exchange,提问作者PortyR
相关产品推荐
相关产品推荐

