必须先过滤再合并:遍历二维数组,对每个子数组用array_filter($sub, fn($v) => $v !== null)剔除null值,再array_merge合并;非数组项跳过,确保安全。

用 array_merge(...array_values($arr)) 无法直接去 null,得先清理
PHP 里把二维数组压平成一维,很多人第一反应是 array_merge(...array_values($arr)) 或 array_reduce,但这些操作本身不处理 null。如果原数组里有 null 元素(比如某行是 null、[] 或 [null, null]),它们会原样进入结果,甚至引发 array_merge() 警告(因为传入了非数组)。
所以必须拆成两步:先递归/逐层过滤掉 null 和空数组,再合并。
- 直接对子数组调用
array_filter($sub)可去掉其中的null、false、0、''—— 但如果你只想去null,得加回调:array_filter($sub, function($v) { return $v !== null; }) - 如果子项本身是
null(如[$a, null, $c]),要先用外层array_filter剔除这些“空槽位” -
array_merge(...)展开时,遇到非数组会报 Warning,务必确保每个子项都经过is_array()校验或兜底为[]
最简安全写法:循环 + array_filter + array_merge
不用递归,只处理一层嵌套(即标准二维数组),下面这段代码兼顾可读性与健壮性:
$flat = [];
foreach ($arr as $sub) {
if (is_array($sub)) {
$filtered = array_filter($sub, function($v) { return $v !== null; });
$flat = array_merge($flat, $filtered);
}
}
它不会误删 0、false 或空字符串,只精准剔除 null;也跳过非数组项(比如某个键值是字符串或对象),避免崩溃。
立即学习“PHP免费学习笔记(深入)”;
- 若允许删除所有“falsy”值(包括
0、''),可简化为array_filter($sub) - 若源数组键名重要(比如要保留原始索引映射),就别用
array_merge,改用$flat[] = ...追加,再用array_values重排 - 性能上,
foreach比array_reduce更直观,也更容易插日志或调试断点
用 array_walk_recursive 的陷阱:它会扁平化所有层级,且无法区分 null 来源
array_walk_recursive 看似省事,但它会钻进**任意深度**的嵌套,把三维、四维也一起拉平。更麻烦的是:它遍历过程中遇到 null 会跳过,但你无法知道这个 null 是来自叶子节点,还是中间某层被 unset 的键——也就没法判断是否该整个子结构丢弃。
- 它不返回新数组,只能靠引用变量收集,写法绕且易错
- 如果二维数组里混着对象或资源,
array_walk_recursive会静默失败或抛出警告 - 即使只想要二维→一维,它也会把
[[1,2], [3, [4,5]]]变成[1,2,3,4,5],失去结构边界
注意 null 的三种常见形态:值、键、子数组本身
实际数据中,null 可能出现在三个位置,处理逻辑完全不同:
- 子数组内某个值是
null→ 用array_filter($sub, fn($v) => $v !== null) - 整个子项是
null(如[1, null, 3]中那个null)→ 外层array_filter($arr, 'is_array')或显式if (is_array($sub)) - 子数组是
null(即$arr[1] === null)→ 必须在外层过滤,否则foreach会把它当null进入循环体,触发后续警告
漏掉任何一种,结果就可能多出 null 或崩掉。尤其从 JSON 解析来的数据,null 出现频率远高于预期。











