
本文介绍在 codeigniter 中通过 php 数组操作将主表(如商品表)与从表(如价格表)关联,并构建以主表记录为顶层、从表记录为子数组的结构化多维数组,适用于一对零或多关系场景。
本文介绍在 codeigniter 中通过 php 数组操作将主表(如商品表)与从表(如价格表)关联,并构建以主表记录为顶层、从表记录为子数组的结构化多维数组,适用于一对零或多关系场景。
在实际开发中,常需将主表(如 pj_barang)与关联的从表(如 pj_detailsupplier)数据合并成层级结构——即每个商品条目下携带其全部对应价格记录(可能为零条或多条)。由于 CodeIgniter 原生查询未直接提供“嵌套分组”能力,需在 PHP 层完成逻辑聚合。
✅ 正确实现思路:以主表为基准,逐条匹配从表数据
核心原则是:遍历 $barang(主表结果),对每条记录查找所有匹配的 $harga(从表结果)项,并聚合为 dataharga 子数组。原代码中使用 array_search + array_column 仅能匹配第一条,且未处理一对多情况;而需求示例中明确要求 dataharga 是数组(即使单条也应为 [0] => [...]),因此需支持多条价格记录。
以下是优化后的完整实现(兼容零条、一条或多条价格记录):
// 执行查询(保持原有逻辑,但推荐使用 LEFT JOIN 一次性获取,见下方说明)
$barang = $this->db
->select('pj_barang.*')
->where('dihapus', 'tidak')
->get('pj_barang')
->result_array();
$harga = $this->db
->select('pj_detailsupplier.*')
->get('pj_detailsupplier')
->result_array();
// 构建 id_barang → 价格记录列表的映射(高效 O(1) 查找)
$hargaMap = [];
foreach ($harga as $h) {
$id = $h['id_barang'];
if (!isset($hargaMap[$id])) {
$hargaMap[$id] = [];
}
$hargaMap[$id][] = $h;
}
// 主表逐条注入 dataharga 子数组
foreach ($barang as &$item) {
$id = $item['id_barang'];
// 若无对应价格,则赋予空数组(更符合语义,比填充空字符串更合理)
$item['dataharga'] = $hargaMap[$id] ?? [];
}
unset($item); // 解除引用,避免意外修改
// 输出结果
print_r($barang);? 关键改进点说明
- 支持一对多:使用 foreach ($harga as $h) 构建 $hargaMap[$id][],天然支持同一 id_barang 对应多条价格记录;
- 性能更优:$hargaMap 预处理时间复杂度为 O(n),后续每次查找为 O(1),远优于嵌套循环的 O(m×n);
- 语义清晰:dataharga 始终为数组(即使为空),避免 ['id_barang' => "", 'harga' => ""] 这类冗余占位符,提升后续 JSON 序列化与前端消费的健壮性;
- 安全解引用:使用 &$item 后及时 unset($item),防止 PHP 引用残留导致数据污染。
⚠️ 注意事项与最佳实践
-
数据库层优化建议:若业务允许,优先考虑在 SQL 层完成关联(如 LEFT JOIN),再用 PHP 分组。例如:
$this->db->select('pj_barang.*, pj_detailsupplier.harga, pj_detailsupplier.id_supplier'); $this->db->from('pj_barang'); $this->db->join('pj_detailsupplier', 'pj_barang.id_barang = pj_detailsupplier.id_barang', 'left'); $this->db->where('pj_barang.dihapus', 'tidak'); $result = $this->db->get()->result_array(); // 再用上述 $hargaMap 方式分组 —— 减少两次独立查询的网络开销 - 空值处理:$hargaMap[$id] ?? [] 比 isset() 判断更简洁;避免向数组写入空字符串,保持数据类型一致性;
- ID 类型注意:确保 id_barang 在两表中类型一致(如均为整型),避免因 '01' !== 1 导致匹配失败。
该方案兼顾可读性、性能与扩展性,是 CodeIgniter 等轻量框架中处理一对多嵌套数据的典型实践。


















