首选判断方式是is_object($var) && $var instanceof \Generator,它兼容PHP 5.5+且安全;is_iterable()不可替代,因其对数组等也返回true,无法精准识别生成器。

如何用 gettype() 和 is_object() 快速识别生成器
PHP 中生成器(Generator)本质是特殊对象,但 gettype($gen) 返回的是 "object",不是 "generator";直接用 is_generator($var) 会报错——PHP 没这个函数。最稳妥的判断方式是结合类型和类名:
-
is_object($var) && $var instanceof \Generator是首选,兼容 PHP 5.5+ -
get_class($var) === 'Generator'可用,但不推荐:若变量为null或非对象会警告 -
gettype($var) === 'object' && get_class($var) === 'Generator'多余冗余,不如直接用instanceof
为什么 is_iterable() 不能代替生成器检测
is_iterable($var) 对生成器返回 true,但它同样对数组、Traversable 实现类、普通对象(含 __iterable)都返回 true。如果你需要**专门分流处理生成器逻辑**(比如调用 ->valid()、->send() 或检查是否已关闭),仅靠 is_iterable() 会误判。
- 数组和生成器都能
foreach,但数组没有->current()方法调用风险 -
Generator对象可能处于已关闭状态,->valid()会返回false,而数组永远“有效” - 想做“仅对生成器启用协程式恢复逻辑”,必须精确识别,不能降级为
is_iterable
实战中容易忽略的边界情况
生成器一旦执行完毕或被显式关闭($gen->close()),它仍是 Generator 实例,instanceof \Generator 仍为 true,但后续调用 ->current() 或 ->next() 会触发致命错误:Exception: Cannot traverse an already closed generator。
- 判断前先用
$gen->valid()确认是否可继续迭代(注意:首次未next()前也返回false) - 不要依赖
empty($gen):生成器不支持empty,会触发警告并返回true - 反射检测
(new \ReflectionGenerator($gen))->getExecuting()可查运行态,但仅限活跃生成器,已关闭的会抛出InvalidArgumentException
一个安全的生成器类型封装函数示例
如果项目中高频判断,建议封装一个带状态感知的工具函数:
立即学习“PHP免费学习笔记(深入)”;
function is_active_generator($var): bool
{
if (!($var instanceof \Generator)) {
return false;
}
// 避免在已关闭状态下反射失败
try {
$ref = new \ReflectionGenerator($var);
return $ref->getExecuting() || $var->valid();
} catch (\Exception $e) {
return false; // 已关闭或不可反射
}
}
这个函数不保证生成器“一定有下一个值”,但能排除已彻底终止的实例,比单纯 instanceof 更贴近真实使用意图。真正要用时,还是得配合 try/catch 捕获 Generator 方法调用异常——毕竟 PHP 的生成器状态管理是隐式的,没捷径绕过运行时校验。











