is_countable 是 php 7.3.0 新增函数,php 7.2 及更早版本不存在,直接调用会触发 fatal error;需手动 polyfill,且必须在所有业务代码前加载。

is_countable 在 PHP 7.2 中根本不存在 —— 它是 PHP 7.3.0 才引入的。如果你在 7.2 或更低版本里直接调用 is_countable,会触发 Fatal error: Uncaught Error: Call to undefined function is_countable()。
PHP 7.2 及更早版本没有 is_countable
官方文档和所有变更日志都明确标注:该函数首次出现在 PHP 7.3.0。PHP 7.2 调用它必然报错,不存在“兼容开关”或隐式降级。很多开发者误以为它在 7.2 可用,是因为升级后没清缓存、或实际运行环境仍是 7.1/7.2,却误读了文档版本号。
手动实现 is_countable 的安全 polyfill
必须自己补全函数定义,且不能依赖任何 7.3+ 特性。以下是最小可用、无副作用的写法:
if (!function_exists('is_countable')) {
function is_countable($var): bool {
return is_array($var) || ($var instanceof Countable);
}
}
注意几个关键点:
-
is_array($var)必须放在前面 —— 因为Countable是接口,is_array对数组返回true,而数组不是对象,$var instanceof Countable会直接false,不会报错 - 不要加
is_object($var)判断前置条件 ——instanceof对非对象安全,PHP 会静默返回false,加了反而多一次类型判断 - 不要试图兼容
ArrayObject或ArrayIterator的特殊情况 —— 它们本身已实现Countable,polyfill 自动覆盖 - 不要用
count($var) !== null或@count($var)做探测 —— 这会在 PHP 7.2+ 触发E_WARNING,违背“无副作用”原则
为什么不能只用 is_array 替代 is_countable
很多旧代码用 is_array($x) && count($x) > 0 判断“是否为非空数组”,但这漏掉了大量合法可数对象:
- Laravel 的
Collection、Symfony 的ArrayCollection - WordPress 的
WP_Posts_Query返回结果(常为WP_Object_Cache包装对象) - 自定义分页器、数据集类,只要实现了
Countable::count()
一旦这些对象传入只认 is_array 的逻辑,就会被当成“空”或跳过处理,造成数据丢失或流程中断 —— 这比警告更危险。
在 PHP 7.1 上用 count 前必须加防护
PHP 7.2+ 对不可数类型调用 count 会发 E_WARNING;PHP 7.1 及更早则静默返回 1(除 null 返回 0),行为不一致。所以跨版本最稳方案是:
- 永远先过
is_countable(polyfill 后)再调count - 避免
count((array)$x)强转 —— 它把对象变成带属性名的关联数组,可能破坏结构(比如stdClass转成['prop' => 'val'],但原对象本不可数) - 不要用
!empty($x)替代 ——empty([0])是true,但数组明明有元素
真正容易被忽略的是:polyfill 必须在所有业务代码加载前执行,且不能被条件 require 分散 —— 否则某处先调了 count 再加载 polyfill,就来不及了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











