简体   繁体   English

PHP - 如何检查两个引用是否指向相同的底层 object(内存地址)?

[英]PHP - how to check two references are pointing to the same underlying object (memory address)?

I am from Java background and sort of new to PHP.我来自 Java,对 PHP 有点陌生。

I am wondering whether there is a PHP equivalent to Java's "==" operation which basically checks whether two references are referring to the exact same underlying object. (PHP's == and === are more like Java's equals method, which is checking whether both underlying objects have the same value)我想知道是否有一个 PHP 等同于 Java 的“==”操作,它基本上检查两个引用是否引用完全相同的底层 object。(PHP 的 == 和 === 更像 Java 的 equals 方法,它检查是否两个底层对象具有相同的值)

Clarification: My question is not about the differences between == and === in PHP nor how to compare values in PHP. I am looking for a way to see whether 2 variables are referring to the same object/memory address.澄清:我的问题不是关于 PHP 中 == 和 === 之间的差异,也不是关于如何比较 PHP 中的值。我正在寻找一种方法来查看 2 个变量是否引用相同的对象/内存地址。 The same object/memory address means that when I update variable $a, $b also needs to be updated and vice versa because $a and $b are referring to the same thing.相同的对象/内存地址意味着当我更新变量 $a 时,$b 也需要更新,反之亦然,因为 $a 和 $b 指的是同一事物。

=== only show if the two variable have the same type and value, but cannot show if the two variable is point to the same address. ===仅显示两个变量是否具有相同的类型和值,但无法显示两个变量是否指向相同的地址。

Php not expose this whether two variable point to the same address.无论两个变量是否指向相同的地址,php 都不会公开这一点。

But you can get it with some workaround.但是您可以通过一些解决方法来获得它。

Way 1. get it with debug information, for example var_dump or debug_zval_dump() .方式 1. 使用调试信息获取它,例如var_dumpdebug_zval_dump()

Way 2. modify variable $a , and check if $ b also is modified.方式2.修改变量$a ,并检查$ b 是否也被修改。

When using the comparison operator (==), the variables of each object are compared in a simple way, that is: two instances of an object are equal if they have the same attributes and values (the values are compared with ==), and they are instances of the same class.使用比较运算符(==)时,比较每个对象的变量的方式比较简单,即:一个对象的两个实例如果属性和值相同,则它们相等(值用==进行比较),它们是同一个类的实例。

When the identity operator (===) is used, the variables of an object are identical yes and only if they refer to the same instance of the same class.当使用身份运算符 (===) 时,对象的变量是相同的,并且仅当它们引用同一类的同一实例时。

Other answers here seem to be missing the specific requirement to check if two instances of an object are the same in memory .这里的其他答案似乎缺少检查 object 的两个实例在 memory 中是否相同的具体要求。 This is NOT the same thing as checking if two classes have identical properties!这与检查两个类是否具有相同的属性不同!

PHP's === operator on objects will only return true when both objects share the same memory address. PHP 的对象===运算符仅在两个对象共享相同的 memory 地址时才返回 true。 This doesn't apply to other primitive types ( strings , floats , etc.), which can have the same type and value, but have unique memory addresses.这不适用于其他原始类型( stringsfloats等),它们可以具有相同的类型和值,但具有唯一的 memory 地址。

PHP gives each unique object an integer ID during the request lifecycle: if two classes expose properties with different names but the same object ID, modifying the property in one class will cause it to be modified in the other. PHP 在请求生命周期中为每个唯一的 object 提供一个 integer ID:如果两个类公开具有不同名称但相同 object ID 的属性,修改一个 class 中的属性将导致它在另一个中被修改。

You can use spl_object_id() to uniquely identify objects in memory:可以使用spl_object_id()来唯一标识 memory 中的对象:

$users = Database::getAllUsers()->mapRowsToObjects();

$people = new People($users->all());
$heroes = new Heroes($users->withSuperPowers());

$superMan  = $heroes->withAlias('Superman')->first();
$clarkKent = $people->named('Clark Kent')->first();


$superMan->location  = 'Krypton';
$clarkKent->location = 'Metropolis';

echo spl_object_id($superman);  // 4207
echo spl_object_id($clarkKent); // 4207
var_export($superman === $clarkKent); // true

// Because these objects share the same ID, changing one affects them both:
echo $superMan->location; // 'Metropolis'

The serialize function can be abused to check if two variables are the same.可以滥用序列化函数来检查两个变量是否相同。

<?php

// check if two variables are the same reference
function same(&$a, &$b) {
  // serialize an array containing only the two arguments
  // check if the serialized representation ends with a reference.
  return substr(serialize([&$a, &$b]), -5) === 'R:2;}';
}

$a = 4;
$b = &$a;
$c = 4;

echo "same(\$a, \$b) === " . var_export(same($a, $b), true) . "\n";
echo "same(\$a, \$c) === " . var_export(same($a, $c), true) . "\n";
echo "same(\$b, \$c) === " . var_export(same($b, $c), true) . "\n";

// same($a, $b) === true
// same($a, $c) === false
// same($b, $c) === false

?>

Warning:警告:

  • Magic methods like __serialize() or __sleep() can cause side effects. __serialize() 或 __sleep() 之类的魔术方法会导致副作用。
  • Performance may suffer if your variables are large objects.如果您的变量是大对象,性能可能会受到影响。
  • If PHP changes the serialization output in a new version, this function may break.如果 PHP 在新版本中更改了序列化输出,则此功能可能会中断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM