is_array()只识别PHP原生数组类型,对ArrayObject或实现ArrayAccess的对象均返回false,因其底层仅检查zval类型是否为IS_ARRAY,而此类对象类型均为IS_OBJECT。

is_array() 对对象数组(即实现了 ArrayAccess 的对象)始终返回 false,因为它只认 PHP 原生数组类型,不识别任何对象——哪怕该对象能像数组一样用 [] 访问、支持 foreach 遍历、甚至继承自 ArrayObject 或实现了 ArrayAccess 接口。
为什么 is_array() 判不出 ArrayObject 或自定义容器
PHP 中的类型判断是严格的:is_array() 检查的是变量底层的 zval 类型是否为 IS_ARRAY。而 ArrayObject、stdClass 实例、或你自己写的 MyList implements ArrayAccess,其类型都是 IS_OBJECT,和数组无关。
-
is_array(new ArrayObject([1,2,3]))→false -
is_array($obj)(其中$obj是实现了ArrayAccess的类实例)→false - 即使
isset($obj['key'])和foreach($obj as $v)都正常工作,is_array() 仍不买账
常见误判场景:把 stdClass 当成关联数组
从 JSON 解码得到的对象(json_decode($json) 默认返回 stdClass),常被误认为“就是个数组”。但:
-
is_array(json_decode('{"a":1}'))→false -
is_object(json_decode('{"a":1}'))→true - 直接用
$obj['a']会报错;必须用$obj->a
若代码逻辑未区分,容易触发 Notice: Trying to access array offset on value of type object。
立即学习“PHP免费学习笔记(深入)”;
需要“类数组”兼容时的替代方案
如果业务上真正关心的是“能否像数组一样访问/遍历”,而非严格类型,可组合判断:
- 原生数组:
is_array($var) - 对象型数组:
is_object($var) && $var instanceof ArrayAccess - 完整写法:
is_array($var) || ($var instanceof ArrayAccess) - 更宽泛的可遍历性(含 Generator、Traversable):
is_iterable($var)(PHP 7.1+)
安全判断建议:先 is_array(),再 fallback 到对象检查
不要依赖 count() 或 gettype() 单独判断,前者对非 Countable 对象会警告,后者对 ArrayObject 返回 'object',不是 'array'。
- ✅ 推荐组合:
if (is_array($data) || $data instanceof ArrayAccess) - ✅ 需要遍历支持:
if (is_iterable($data)) - ❌ 避免:
if (count($data) > 0)(可能 warning,且字符串、null 也返回 0) - ❌ 避免:
if (gettype($data) === 'array')(漏掉 ArrayAccess 场景)



















