PHP的in_array()方法如何识别数组中对象的特定实例的存在?

时间:2018-07-24 17:53:17

标签: php arrays object

我遇到了一些有趣的事情:in_array()函数不仅在“ needle”是特定值时起作用,而且在它是特定对象实例时也起作用。我举一个例子:

class Message{
  private $str;
  function __construct($str){
      $this->str= $str;
  }

}

$message1 = new Message('Hey there!');

$message2 = new Message('sup');

$message3 = new Message('yo');

$arr= [$message2, 545,'hey'];

echo in_array($message2 ,$arr) ? 'true' : 'false';

如您所见,我正在创建某个类的不同实例。对这些实例之一的引用被放置到数组中。

当我检查数组中是否存在“ message2”对象时,我得到了 true 。如果我将needle更改为“ message1”或“ message3”,我会得到 false

这是如何工作的?该文档说它“检查数组中是否存在值”。 但是对对象的引用是“值”吗?有人可以澄清这个问题吗?

2 个答案:

答案 0 :(得分:4)

从PHP docs

  

从PHP 5开始,对象变量不再包含该对象本身作为值。它仅包含一个对象标识符,该标识符使对象访问者可以找到实际的对象。当对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们持有标识符的副本,该副本指向同一对象。

在“ OOP” PHP之前(即PHP <5),所有变量均通过 value 传递。您始终可以使用&运算符通过引用传递变量,尽管这与使用指针的C之类的语言不同。在PHP5 +中,对象不是通过引用传递的,但是对象变量不包含对象本身,而是对象的标识符。当您将该变量传递给函数时,该标识符的副本将作为参数发送,就像其他任何原语一样。

要理解的最重要的事情是,当您将对象传递给函数时,对象本身不会传递,而是传递给对象的标识符。这些标识符提供对对象本身的访问权限,同时仍然允许您在实例之间进行数组搜索和相等性比较(===)。

虽然PHP文档有点神秘,但我们可以看到对象标识符实际上是一个值:

  

不同的变量不是别名:它们持有标识符的副本,该副本指向同一对象。

包含对象的变量的值是对象标识符,而不是对象本身。

// $obj contains an identifier to an instance of `MyObject`
$obj = new MyObject();

当您将$obj传递给函数时,该标识符的副本将作为参数发送。 PHP 始终按其值传递变量,除非明确指示使用&$var通过引用传递。因此,要回答您的问题,对对象的引用(或更确切地说是 identifier )实际上是一个可用于比较对象特定实例的值。


修改

正如@Chris Anderson和@Lou所指出的,in_array在默认情况下会进行松散比较。比较两个对象时,==检查它们是相同的实例并具有相同的属性值,而===检查它们是相同的类的实例。除非引起我的误解,否则您最初的问题是询问存储类实例的变量的行为方式,因此我的原始答案足以解决当前的问题。但是,重要的是要注意,如果没有明确要求严格比较(===),则如果对象的值相同,您将得到true

答案 1 :(得分:2)

参考:Comparing Objects

class Message{
    private $str;
    function __construct($str){
      $this->str= $str;
    }
}

$message1 = new Message('Hey there!');
$message2 = new Message('yo');
$message3 = new Message('yo');

$arr = [$message2, 545,'hey'];
//loose comparison using == 
echo in_array($message3 ,$arr) ? 'true' : 'false'; // returns true

//strict comparison using ===
echo in_array($message3 ,$arr, true) ? 'true' : 'false'; // returns false

in_array()

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
  

除非进行了严格设置,否则使用宽松的比较在干草堆中搜索针头。

松散比较(==):

  

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

严格比较(===):

  

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