== 和 === 比较对象均只判断是否为同一实例,永远不比较属性值;若需按内容比较,必须手动实现 equals() 方法。

用 == 比较两个对象,永远返回 false
PHP 中 == 对对象只做“是否为同一实例”的浅层判断,但实际行为是直接返回 false —— 即便两个对象由同一类、同参数构造,== 也不比较属性值。
这是语言设计决定的:对象在 == 下不触发自动属性遍历,也不调用任何魔术方法。它和 === 在这点上表现一致(都只认“同一个内存地址”),但初学者常误以为 == 会像数组那样“松散比较”。
- 别指望
==能判断两个User对象“内容是否相同” - 写测试时若用
self::assertEquals($a, $b)(PHPUnit),底层走的是属性递归比较,和==无关 - 如果真要松散语义,得自己写方法,比如
public function equals(self $other): bool
=== 和 == 对对象的行为完全一样
两者都只检测是否为**同一个对象实例**(即引用相等),不关心类名、属性、状态。没有例外,不看 __toString(),不调用 __equals()(PHP 根本没有这个魔术方法)。
示例:
立即学习“PHP免费学习笔记(深入)”;
$a = new DateTime('2024-01-01');
$b = new DateTime('2024-01-01');
var_dump($a == $b); // bool(false)
var_dump($a === $b); // bool(false)
$c = $a;
var_dump($a === $c); // bool(true)
- 哪怕两个对象
var_export()输出一模一样,===仍为false - 类型严格性在这里没实际意义——对象类型相同但实例不同,
===就不通过 - 别被“全等更严格”误导:对对象而言,它没机会比
==“更严格”,因为根本没第二层比较逻辑
想按属性值比较?必须手动实现 equals() 方法
PHP 不提供默认的对象值比较机制,也没有接口强制你实现。是否相等、按哪些字段比、是否忽略 null 或空字符串,全由你定义。
常见陷阱:
- 忘记检查
$other是否为同一类:if (! $other instanceof static) return false; - 直接
return $this == $other;—— 这又绕回引用比较,毫无意义 - 用
get_object_vars()但没处理嵌套对象或动态属性(__get) - 在 DTO 或 Entity 中漏掉新添加的属性,导致测试偶然通过、上线后出错
简单安全的做法:
public function equals(self $other): bool
{
return $this->id === $other->id
&& $this->name === $other->name
&& $this->email === $other->email;
}
serialize() 或 json_encode() 不适合做对象比较
有人图省事把对象序列化再比字符串,看似能绕过引用限制,但隐患极多:
-
serialize()包含类名、私有属性前缀、PHP 版本相关格式,换环境就失效 -
json_encode()会丢弃私有/受保护属性、方法、资源、循环引用,且顺序不保证(PHP 8.0+ 关联数组键序才稳定) - 浮点数精度、时间格式(
DateTime默认输出带微秒)、null vs 空字符串等细节极易导致假阴性 - 性能差:序列化是重操作,尤其对大对象或深嵌套结构
真要快速验证(仅限调试),可用 var_export($obj, true) + 手动清理,但生产代码中必须用明确字段的 equals()。
对象比较这件事,没有银弹。写清楚比什么、怎么比、边界在哪,比找一个“通用解法”重要得多。











