
本文介绍在 php 中对多维关联数组按指定键(如 id、name 等)分组,将重复项的差异化字段(如 sections)自动合并为数组,保留唯一主干信息,适用于报表汇总、权限归并等典型场景。
本文介绍在 php 中对多维关联数组按指定键(如 id、name 等)分组,将重复项的差异化字段(如 sections)自动合并为数组,保留唯一主干信息,适用于报表汇总、权限归并等典型场景。
在实际开发中,我们常遇到原始数据以“扁平化行记录”形式存在,但业务逻辑需要按实体聚合(例如同一用户在多个部门/角色/模块下的配置)。此时需将具有相同身份标识(如 id、name、department)的数组项合并为一条,并将变动字段(如 sections)转为数组集合。
核心思路是:构造唯一分组键 → 按键聚合同质项 → 提取公共字段 + 合并差异字段。
以下为推荐实现方案(兼容 PHP 5.6+,无需额外扩展):
$initial_array = [
[
'id' => 2,
'role_id' => 2,
'name' => 'PABLO',
'sections' => 'FINANCE',
'department' => 'FATP',
],
[
'id' => 2,
'role_id' => 2,
'name' => 'PABLO',
'sections' => 'ACCOUNTING',
'department' => 'FATP',
],
];
// 步骤1:定义分组依据字段(即视为“同一实体”的关键字段)
$groupKeys = ['id', 'role_id', 'name', 'department'];
// 步骤2:定义需聚合的字段(将值收集为数组)
$collectField = 'sections';
$grouped = [];
foreach ($initial_array as $item) {
// 构建分组键:用下划线连接关键字段值(避免 & 符号引发歧义,更健壮)
$keyParts = array_map(fn($k) => $item[$k] ?? '', $groupKeys);
$groupKey = implode('_', $keyParts);
// 初始化分组容器(若首次出现该 key)
if (!isset($grouped[$groupKey])) {
$grouped[$groupKey] = array_intersect_key($item, array_flip($groupKeys));
$grouped[$groupKey][$collectField] = [];
}
// 将差异字段值追加到对应分组
$grouped[$groupKey][$collectField][] = $item[$collectField];
}
// 步骤3:提取最终结果(去除中间键,转为索引数组)
$final_array = array_values($grouped);
print_r($final_array);✅ 输出结果:
Array
(
[0] => Array
(
[id] => 2
[role_id] => 2
[name] => PABLO
[department] => FATP
[sections] => Array
(
[0] => FINANCE
[1] => ACCOUNTING
)
)
)? 关键优化说明:
- 使用
implode('_', $keyParts)替代原始示例中的&连接符,规避字段值本身含特殊字符导致键冲突的风险; - 利用
array_intersect_key()安全提取公共字段,避免硬编码索引; - 支持灵活配置
$groupKeys和$collectField,便于复用至其他场景(如按user_id合并permissions,或按product_id合并tags); - 若需去重(如防止重复
sections值),可在追加前使用!in_array(...)或最后调用array_unique()。
⚠️ 注意事项:
- 所有分组键字段必须存在于每条记录中,否则需预处理(如设置默认值);
- 若原始数据量极大(>10,000 条),建议改用数据库
GROUP BY+GROUP_CONCAT提前聚合,减少 PHP 内存压力; - 对于嵌套结构(如
sections本身是数组),需改用递归合并逻辑,本例不适用。
该方法简洁、可读性强,是 PHP 数组聚合任务的标准实践之一。

















