array_unique不能直接去重多维数组,因其底层将子数组转为字符串"Array"导致误判;可用serialize或json_encode先序列化再去重,后者更安全推荐,注意空数组和类型校验。

array_unique 为什么不能直接去重多维数组
array_unique 只能比较一维数组的值,底层用的是字符串或整数的哈希比对。遇到多维数组(比如包含 array、stdClass 或对象的元素),PHP 会把每个子数组转成字符串 "Array",结果所有子项都变成相同字符串,最终只留第一个 —— 看似“去重”了,实则丢失数据且不可控。
用 serialize + array_unique 处理简单多维数组
如果多维数组结构规整(纯 array,不含资源、闭包、对象等无法序列化的值),可先用 serialize 转成唯一字符串标识,去重后再 unserialize 回来:
function array_unique_multidimensional($arr) {
$serialized = array_map('serialize', $arr);
$unique = array_unique($serialized);
return array_map('unserialize', $unique);
}
注意:unserialize 存在安全风险,仅限可信数据;PHP 8.1+ 对含对象的序列化有更严格限制,需确认环境兼容性。
用 json_encode 做轻量级去重(推荐日常使用)
比 serialize 更安全、可读、跨语言友好,适合不含资源、函数、循环引用的数组:
立即学习“PHP免费学习笔记(深入)”;
-
json_encode($item, JSON_THROW_ON_ERROR)可捕获编码失败(如 NaN、Infinity) - 重复项经
json_encode后字符串完全一致,array_unique才真正生效 - 记得用
JSON_FORCE_OBJECT统一索引数组和关联数组的输出格式,避免键顺序导致哈希不一致
示例:
$data = [['id'=>1,'name'=>'a'], ['id'=>2,'name'=>'b'], ['id'=>1,'name'=>'a']];
$encoded = array_map(fn($x) => json_encode($x, JSON_FORCE_OBJECT), $data);
$unique_encoded = array_unique($encoded);
$result = array_map('json_decode', $unique_encoded); // 得到 stdClass 对象
需要保留原数组键名?别忘了 array_values
array_unique 默认保留原始键名,去重后可能产生不连续数字键或混杂字符串键。若后续要遍历或 JSON 输出,通常需要重置为连续数字索引:
- 用
array_values($result)强制重排键名 - 若需保留键名做业务逻辑(如 ID 映射),则跳过这步,但要注意
foreach时键可能跳跃 -
array_unique的第二个参数SORT_STRING/SORT_REGULAR仅影响排序行为,不影响去重逻辑,一般不用改
最常被忽略的是:没检查输入是否为空数组或非数组类型,array_map 在非数组上会报 Warning —— 实际使用前加个 is_array 判断更稳妥。











