php二维转一维不能仅用array_merge($arr),必须用array_merge(...$arr)解包(php≥7.4);深层嵌套需递归、array_walk_recursive或迭代方案,否则漏元素、丢键名、报错。

array_merge 解包最常用,但只适用于二维且 PHP ≥ 7.4;真要处理任意深度嵌套,得用递归或迭代,否则会漏掉三层以上的元素。
用 array_merge(...$arr) 处理严格二维数组
这是最快、最直观的写法,但有硬性前提:外层数组每个元素都必须是一维数组,且 PHP 版本不能低于 7.4。
常见错误现象:array_merge($arr)(没加三个点)会导致整个子数组被当成单个元素塞进结果里,输出类似 [[1,2], [3,4]] 而不是 [1,2,3,4]。
- 必须写成
array_merge(...$arr),...是解包操作符,把每个子数组展开成独立参数传给array_merge - 所有键名会被重置为数字索引,原关联键(如
['a' => 1])直接丢失 - 如果子数组里混了字符串键或非数值键,
array_merge仍能工作,但不会保留这些键名 - 遇到空数组或
null元素会触发 warning,建议提前过滤:array_filter($arr, 'is_array')
用递归函数处理任意深度嵌套
这是最通用的方案,适合树形结构、API 返回的深层嵌套数据(比如含 children 键的菜单或分类)。
容易踩的坑:无限制递归在超深结构(比如 500 层嵌套)下会触发 Fatal error: Maximum function nesting level,PHP 默认栈深度是 256。
- 核心逻辑是判断
is_array($item),是则递归调用自身,否则直接追加到结果 - 必须用
array_merge($result, flatten($item)),不能用array_push($result, ...flatten($item)),否则会把扁平结果整个当一个元素塞进去 - 若需保留原始键路径(如
user.profile.name),得额外传参累积路径,但会显著增加复杂度,一般业务不需要 - 性能上,递归适合“深而窄”的结构(分支少、层级多),对“宽而浅”(一层几百个子数组)反而不如
foreach循环
用 array_walk_recursive 提取终端值
这个函数不返回新数组,而是遍历到底层标量值(string/int/bool/null),跳过所有中间数组节点。适合“只要叶子值,不要结构”的场景,比如从嵌套配置中提取所有邮箱地址。
典型误用:想拿它来保留某些键(如只取所有 name 字段),但它不提供当前键名上下文,无法做条件判断。
- 它天然忽略数组键,只对最终非数组值执行回调,所以无法区分
['name' => 'A']和['title' => 'A'] - 如果数组里有对象或资源,
array_walk_recursive会跳过它们,不报错也不警告 - 不能控制遍历顺序(实际是深度优先),也不支持中断或跳过某一分支
- 配合引用变量收集结果即可:
$flat = []; array_walk_recursive($arr, function($v) use (&$flat) { $flat[] = $v; });
大数组或不确定深度时优先选迭代方式
递归函数看着简洁,但一旦嵌套过深或元素过多,就容易爆栈或内存溢出。这时候用显式栈(stack)模拟递归更稳妥。
关键区别在于:递归靠函数调用栈,迭代靠自己维护的数组栈;前者深度受 PHP 配置限制,后者只受限于可用内存。
- 初始化一个栈,把原始数组压入:
$stack = [$arr]; - 循环弹出栈顶元素,如果是数组就将其每个子项再压入栈;否则直接追加到结果
- 注意顺序:用
array_unshift压栈可模拟递归的顺序,用array_push则是逆序 - 比递归多几行代码,但能安全处理几千层嵌套,也方便加深度限制(比如只展开前 10 层)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











