Подтвердить что ты не робот

Неожиданный результат при сравнении объектов PHP

Когда я сравнивал два разных объекта, он сначала возвращает true, а после print_r (по объектам) возвращается false.

Из руководства PHP:

Два экземпляра объекта равны, если они имеют одинаковые атрибуты и значения и являются экземплярами одного и того же класса.

Но здесь, в примере, я устанавливаю разные значения. Почему результат отличается от PHP 5.4.0 - 5.5.7?

abstract class first
{
    protected $someArray = array();
}     

class second extends first
{    
    protected $someArray = array();        
    protected $someValue = null;

    public function __construct($someValue)
    {
        $this->someValue = $someValue;
    }
}

    $objFirst = new second('123');       
    $objSecond = new second('321');       

    var_dump ($objFirst == $objSecond);    
    print_r($objFirst);    
    var_dump ($objFirst == $objSecond);

Результат:

 bool(true)
 second Object ( [someArray:protected] =>
 Array ( ) [someValue:protected] => 123 )
 bool(false)

Но я ожидал:

  bool(false)
  second Object ( [someArray:protected] =>
  Array ( ) [someValue:protected] => 123 )
  bool(false)
4b9b3361

Ответ 1

Это была ошибка в PHP. Теперь он исправлен, см. commit. Короче говоря:

  • Если вы расширяете класс и переопределяете одно и то же свойство, properties_table объекта заканчивается значением NULL.
  • Сравнительный код неправильно прервал сравнение, когда два объекта имели значение NULL в properties_table в том же самом индексе, сообщая об объектах как равные. Разумеется, это не имеет никакого смысла, поскольку оно отбрасывает все различия в следующих свойствах. Теперь это исправлено.
  • Причина, по которой print_r изменяет результат, заключается в том, что путем извлечения свойств объекта (get_properties) свойства hashtable перестраиваются (rebuild_properties_table), который использует совершенно другой (и правильный) код сравнения.
  • Для контекста properties_table и properties - два разных способа использования PHP для представления свойств - первый из них является более эффективным и используется для объявленных свойств, а последний используется для динамических свойств. Вызов print_r эффективно делает свойства объекта динамическими.