繁体   English   中英

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

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

我来自 Java,对 PHP 有点陌生。

我想知道是否有一个 PHP 等同于 Java 的“==”操作,它基本上检查两个引用是否引用完全相同的底层 object。(PHP 的 == 和 === 更像 Java 的 equals 方法,它检查是否两个底层对象具有相同的值)

澄清:我的问题不是关于 PHP 中 == 和 === 之间的差异,也不是关于如何比较 PHP 中的值。我正在寻找一种方法来查看 2 个变量是否引用相同的对象/内存地址。 相同的对象/内存地址意味着当我更新变量 $a 时,$b 也需要更新,反之亦然,因为 $a 和 $b 指的是同一事物。

===仅显示两个变量是否具有相同的类型和值,但无法显示两个变量是否指向相同的地址。

无论两个变量是否指向相同的地址,php 都不会公开这一点。

但是您可以通过一些解决方法来获得它。

方式 1. 使用调试信息获取它,例如var_dumpdebug_zval_dump()

方式2.修改变量$a ,并检查$ b 是否也被修改。

使用比较运算符(==)时,比较每个对象的变量的方式比较简单,即:一个对象的两个实例如果属性和值相同,则它们相等(值用==进行比较),它们是同一个类的实例。

当使用身份运算符 (===) 时,对象的变量是相同的,并且仅当它们引用同一类的同一实例时。

这里的其他答案似乎缺少检查 object 的两个实例在 memory 中是否相同的具体要求。 这与检查两个类是否具有相同的属性不同!

PHP 的对象===运算符仅在两个对象共享相同的 memory 地址时才返回 true。 这不适用于其他原始类型( stringsfloats等),它们可以具有相同的类型和值,但具有唯一的 memory 地址。

PHP 在请求生命周期中为每个唯一的 object 提供一个 integer ID:如果两个类公开具有不同名称但相同 object ID 的属性,修改一个 class 中的属性将导致它在另一个中被修改。

可以使用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'

可以滥用序列化函数来检查两个变量是否相同。

<?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

?>

警告:

  • __serialize() 或 __sleep() 之类的魔术方法会导致副作用。
  • 如果您的变量是大对象,性能可能会受到影响。
  • 如果 PHP 在新版本中更改了序列化输出,则此功能可能会中断。

暂无
暂无

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

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