array_count_values() 仅支持标量值,对象因非标量且无法作键而报错;统计对象次数需先转唯一标识:用 spl_object_id()(实例级)、serialize()/json_encode()(内容级)或自定义 gethashkey()(业务级)。

因为 PHP 的 array_count_values() 只支持标量值(string、integer、float、boolean、null),不支持对象、数组、资源等复合类型。
为什么对象会报错
当你把包含对象的数组传给 array_count_values(),PHP 会尝试将每个元素作为“键”去哈希统计。但对象不能直接用作数组键(内部会调用 __toString(),若未定义则触发致命错误),更关键的是该函数底层根本不接受非标量类型——它会在遇到第一个对象时立刻抛出 Warning: array_count_values(): Can only count string and integer values 并返回 false。
怎么统计对象出现次数(实用方案)
你需要先将对象“可比较地”转化为唯一标识,再统计。常见做法有:
-
用 spl_object_id() 转为整数 ID:每个对象有唯一 ID,适合判断是否是同一个实例(内存地址级)
$ids = array_map('spl_object_id', $objects);<br>$counts = array_count_values($ids); -
用 serialize() 或 json_encode() 转为字符串:适合判断对象内容是否完全相同(需确保属性顺序、类型一致)
$strs = array_map('serialize', $objects);<br>$counts = array_count_values($strs); -
自定义唯一标识(推荐):在对象中加一个
getHashKey()方法,返回业务上能代表“相等性”的字符串,比如$obj->id . '|' . $obj->status,再统计这个键。
注意边界情况
直接用 serialize() 统计要注意:
– 私有/受保护属性、对象内部引用、闭包、资源等会导致序列化失败或不可比;
– 两个属性相同但实例不同的对象,serialize() 结果可能不同(因含类名、命名空间等);
– spl_object_id() 在对象销毁后 ID 可能复用,所以只适用于当前生命周期内的统计。











