
怎么用 is_object() 判断变量是不是对象
最直接、最安全的方式就是用 PHP 内置函数 is_object()。它专为这事设计,不依赖类型转换,也不受魔术方法干扰。
常见错误是拿 gettype($var) === 'object' 或 get_class($var) 来判断——前者在 null 或资源上可能漏判,后者遇到非对象会直接报 get_class(): Argument #1 ($object) must be of type object 致命错误。
使用场景包括:函数参数校验、反序列化后类型兜底、框架中做依赖注入前的类型断言。
-
is_object(null)→false -
is_object(new stdClass())→true -
is_object([])→false -
is_object($obj)对任何对象(含匿名类、PDO 实例、自定义类)都返回true
为什么不能用 instanceof 替代 is_object()
instanceof 是类型关系判断,不是“是否为对象”的通用检测工具。它要求左侧操作数必须是对象,否则直接报错或返回 false(PHP 8.0+ 对非对象左值返回 false,但 PHP 7.x 会 fatal error)。
立即学习“PHP免费学习笔记(深入)”;
比如你传了个 null 或数组进去:null instanceof stdClass 在 PHP 7.4 下直接崩溃,而 is_object(null) 始终安全返回 false。
性能上没差别,但健壮性差一截。别为了省一个函数调用去赌输入一定合法。
- 想确认“是不是某个类的实例”?用
instanceof - 只想知道“是不是对象”?只用
is_object() - 不确定变量来源(比如来自 JSON 解码、用户输入、缓存反序列化)?必须先过
is_object()
is_object() 和 gettype() 的兼容性差异
is_object() 自 PHP 4 就存在,所有版本行为一致;gettype() 返回字符串,在 PHP 8.0+ 对某些内部对象(如 Closure、Generator)仍返回 'object',但对 WeakMap、Fiber 等新类型也返回 'object' —— 表面看没问题,实际掩盖了类型演进带来的语义变化。
更麻烦的是,gettype() 无法区分对象和资源(比如 curl_init() 返回资源,gettype() 返回 'resource'),而你如果写错了条件,很容易把资源当对象处理。
- PHP 5.6–8.3:
is_object(STDIN)→false(STDIN是资源) -
gettype(STDIN)→'resource',但有人误写成gettype($x) === 'object'就漏掉了这个分支 - 第三方库返回
__toString()可能被误认为“像对象”,但is_object()不吃这套
反序列化后一定要再 check 一次 is_object()
PHP 反序列化本身不保证结果一定是对象。比如 unserialize('a:0:{}') 得到空数组,unserialize('N;') 得到 null,甚至恶意构造的 payload 可能触发异常或返回意外类型。
很多开发者以为 “我反序列化的是 class 字符串,那结果肯定是个对象”,但只要中间有一步失败(比如类未加载、__wakeup() 抛异常、PHP 版本不兼容),结果就不是对象。
- 反序列化后立刻用
if (!is_object($data)) { throw new InvalidArgumentException('Expected object'); } - 别依赖
class_exists()或method_exists()替代类型判断——它们不检查变量本身是不是对象 - 在
__unserialize()中也不能跳过这步,因为父类或扩展逻辑可能绕过你的校验
真正容易被忽略的是:对象可能被 __set_state()、json_decode() + 类型强制转换等间接方式“伪装”出来,但只有 is_object() 能一锤定音。别的都是猜。











