php中判断数组维数需递归实现:空数组返回1,标量返回0,非空数组深度为1+子元素最大深度;需防循环引用和类型误判,推荐用array_reduce配合匿名递归函数。

怎么用 PHP 判断一个数组是几维的
PHP 没有内置函数直接返回「维数」,is_array() 只能判断是不是数组,不能区分一维、二维还是嵌套很深的结构。得自己递归探查——但别写成无限递归,也别漏掉空数组或混合类型(比如键是字符串、值里混着数字和数组)的情况。
核心思路:对每个元素,如果是数组就继续往下钻,记录深度;不是数组就停住。关键是要统一“深度”的定义:空数组 [] 算 1 维,不是 0 维;纯标量(如 42 或 "hello")深度为 0。
- 用
array_reduce()+ 匿名递归函数最简洁,避免全局函数污染 - 必须加
is_array($item)判定,否则遇到对象、资源会报 Warning - 遇到非数组项(如
null、false、数字),直接返回 0,不参与深度计算 - 如果数组里所有元素都不是数组(比如
[1, "a", true]),最大深度就是 1
递归函数容易踩的坑:空数组、引用、非数组值
很多人写的版本在遇到 [] 时返回 0 或直接崩,其实空数组明确属于「一维数组」,应该返回 1。更隐蔽的问题是循环引用——比如 $arr = []; $arr['self'] = &$arr;,不加检测会栈溢出。
- 开头先用
=== []或empty($arr) && is_array($arr)特判空数组,直接返回 1 - 用
spl_object_hash()配合递归时的已访问数组 ID 记录,可防循环引用(小项目可省,但线上数据不可控时建议加) -
foreach遍历时,值可能是引用(&$v),但深度计算只关心类型,不用解引用 - 别用
count($arr, COUNT_RECURSIVE)代替维数判断——它统计的是总元素个数,不是嵌套层级
性能和兼容性:PHP 7.4+ 可用箭头函数简化,但要注意作用域
PHP 7.4 支持箭头函数,写递归更紧凑,但它不能递归调用自身(没有函数名),所以必须配合变量赋值 + fn 闭包。PHP 8.0+ 的 match 表达式在这里没优势,别硬套。
立即学习“PHP免费学习笔记(深入)”;
- 推荐写法:
$depth = fn($arr) => empty($arr) && is_array($arr) ? 1 : (is_array($arr) ? 1 + array_reduce($arr, fn($carry, $item) => max($carry, $depth($item)), 0) : 0); - 注意:这个
$depth变量必须在定义后才能被闭包捕获,不能写成return fn(...) => ... $depth(...)这种顺序错误 - PHP 7.2–7.3 要用
function ($arr) use (&$depth)显式传引用,否则报Undefined variable: depth - 对超大嵌套数组(深度 > 100),PHP 默认
xdebug.max_nesting_level=256可能不够,需调高或改用栈模拟递归
实际使用场景:验证 API 返回结构、配置文件合法性
常见需求不是“求维数”,而是“确保这个配置不能超过二维”或“接口返回的 data 字段必须是二维数组”。这时候硬算最大深度不如加约束检查。
- 校验二维限制:
array_walk($arr, function($v) { if (!is_array($v)) throw new InvalidArgumentException("data must be 2D"); });比先算维数再比大小更快 - JSON 解码后可能得到
null或对象,务必先is_array($data),否则递归函数会警告 - 多维关联数组(如
["users" => [["id" => 1], ["id" => 2]]])常被误判为「三维」,其实业务上它只是「带一层键的二维数据」,维数函数不管键名,只看嵌套结构 - 如果要区分「规则二维表结构」和「任意嵌套」,光靠维数不够,得结合
array_keys($arr[0] ?? [])是否一致来判断
维数本身是个脆弱指标——同是二维,[[1,2], [3,4]] 和 ["a" => [1,2], "b" => [3]] 行为差异很大。真正在意的往往不是数字,而是“能否用双重 foreach 安全遍历”或者“是否符合预期 schema”。











