最直接的方法是用 array_keys() 配合递归函数;array_walk_recursive() 只访问叶子节点键名,会漏掉中间层键;需路径信息时应手动拼接当前路径;遇到非数组类型(如对象、资源)需提前判断并处理。

用 array_keys() 配合递归遍历最直接
PHP 原生 array_keys() 默认只取第一层键,要拿所有层级的键名,必须自己递归。别指望它自动扁平化嵌套结构——这是常见误解。
实操建议:
- 写一个递归函数,每次调用
array_keys()拿当前层级键,再对每个值是数组的元素继续递归 - 用引用传参或返回合并后的键名数组,避免反复拼接开销
- 注意区分数字键和字符串键(比如
0和"0"),array_keys()默认都返回原类型,无需强制转换
function collectAllKeys($arr, &$keys = []) {
foreach (array_keys($arr) as $key) {
$keys[] = $key;
if (is_array($arr[$key])) {
collectAllKeys($arr[$key], $keys);
}
}
return $keys;
}
用 array_walk_recursive() 会漏掉中间层键名
这个函数只访问“叶子节点”(即最终非数组值)对应的键,跳过所有中间数组的键。如果你需要完整路径(比如 ["user"]["profile"]["name"]),它完全不适用。
典型错误现象:
- 输入
["a" => ["b" => ["c" => 1]]],只拿到["c"],而"a"和"b"被跳过 - 误以为它是“深度遍历”,其实它是“深度值访问”,不暴露容器结构
所以别用它来收集全部键名,除非你明确只要末端键。
想保留键名路径?得手动拼接
如果业务需要知道某个键在哪一层、属于哪条路径(例如调试或生成 JSON Schema),就不能只存键名,还得记录层级关系。
实操建议:
- 递归时传入当前路径数组,比如
["user", "profile"],遇到新键就array_merge($path, [$key]) - 用
implode('.', $path)或json_encode($path)存为字符串便于查看 - 注意性能:路径越深、数组越宽,内存占用增长越快;超大嵌套数组慎用全路径存储
遇到对象或资源类型要提前判断
多维数组里混入 stdClass 对象、mysqli_result 或其他资源时,is_array() 会返回 false,递归会中断,但不会报错——容易静默丢键。
处理建议:
- 在递归入口加
if (!is_array($arr)) return;是安全底线 - 如果必须支持对象,改用
get_object_vars()提取公共属性,但注意它不处理私有/保护属性和动态属性 - 资源类型(如文件句柄)无法被键名遍历,直接跳过最稳妥
实际项目里,混合类型往往意味着数据结构不规范,先清理输入比硬扛更省事。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











