在php项目里,多维数组是非常常见的数据结构,比如后台菜单、商品分类、接口返回的嵌套数据等。当数组层数不固定时,用普通循环很难一次取完所有值,这时候递归遍历就是最直接的解决办法。

为什么需要递归遍历多维数组
假设有一个不确定层级的数组,可能是两层,也可能是五层。如果只用foreach,你需要写多层嵌套,既不优雅也容易漏掉深层数据。递归的核心思想是:如果当前元素是数组,就再次调用自己;如果不是数组,就执行具体逻辑。
手写一个通用的php递归函数
下面这个函数可以遍历任意维度的数组,并对每一个非数组元素调用回调函数。
<?php
// 递归遍历多维数组
function recursive_traverse($data, $callback) {
if (!is_array($data)) {
return;
}
foreach ($data as $key => $value) {
if (is_array($value)) {
// 如果是数组,继续递归
recursive_traverse($value, $callback);
} else {
// 不是数组,执行回调
call_user_func($callback, $key, $value);
}
}
}
// 示例数组
$list = array(
'name' => '张三',
'info' => array(
'age' => 20,
'hobby' => array('篮球', '音乐')
)
);
// 打印每一个叶子节点
recursive_traverse($list, function($k, $v) {
echo $k . ': ' . $v . PHP_EOL;
});
?>
使用array_walk_recursive简化代码
php自带了array_walk_recursive函数,它会对数组中的每个叶子节点应用用户函数,但不会处理子数组本身。
<?php
$list = array(
'a' => 1,
'b' => array('c' => 2, 'd' => array('e' => 3))
);
array_walk_recursive($list, function($value, $key) {
echo $key . '=>' . $value . PHP_EOL;
});
?>
array_walk_recursive的局限
- 无法在回调中知道当前处于第几层
- 不能修改原数组的键结构
- 遇到对象是按数组还是按对象处理容易混淆
带层级参数的递归写法
如果你需要知道元素所在的深度,可以给递归函数加一个层级参数。
<?php
function traverse_with_level($data, $callback, $level = 1) {
if (!is_array($data)) {
return;
}
foreach ($data as $key => $value) {
if (is_array($value)) {
traverse_with_level($value, $callback, $level + 1);
} else {
call_user_func($callback, $key, $value, $level);
}
}
}
$tree = array('x' => array('y' => 10), 'z' => 20);
traverse_with_level($tree, function($k, $v, $lv) {
echo '层级' . $lv . ' ' . $k . ':' . $v . PHP_EOL;
});
?>
注意事项与技巧总结
| 场景 | 推荐方式 |
|---|---|
| 仅需读取叶子值 | array_walk_recursive |
| 需要层级或改写结构 | 自定义递归函数 |
| 超大数组 | 注意递归深度,避免栈溢出 |
在写递归时,一定要有明确的退出条件,比如is_array判断和foreach结束,否则容易变成死循环。另外,php默认递归深度由xdebug.max_nesting_level等配置影响,处理超深数据要考虑迭代替代方案。
递归不是万能的,但理解递归后,你会对多维数组的操作有更清晰的控制力。
php递归多维数组array_walk_recursive遍历修改时间:2026-07-24 23:42:10