За последние 24 часа нас посетили 68325 программистов и 1651 робот. Сейчас ищут 1022 программиста ...

Странное поведение объекта

Тема в разделе "PHP для новичков", создана пользователем Overfinch, 10 май 2016.

Метки:
  1. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Доброго времени суток, изучаю ООП по Мэту Зандстре, и наткнулся на странный код:
    Код (Text):
    1. class Conf {
    2.     private $file;
    3.     private $xml;
    4.     public $lastmatch;
    5.  
    6.  
    7.     public function __construct($file){
    8.         $this->file = $file;
    9.         $this->xml = simplexml_load_file($file);
    10.         var_dump($this->xml[0]);
    11.     }
    12.  
    13.     public function get($str){
    14.         $matches = $this->xml->xpath("/conf/item[@name=\"$str\"]");
    15.         if(count($matches)){
    16.             $this->lastmatch = $matches[0]; // именно когда меняем свойства этому объекту, то меняются свойства $this->xml
    17.             var_dump($this->xml[0]);
    18.             return (string)$matches[0];
    19.         }
    20.         return null;
    21.     }
    22.  
    23.     public function set($key,$value){
    24.         if(! is_null($this->get($key))){
    25.             $this->lastmatch[0] = $value;
    26.             return;
    27.         }
    28.         echo "new";
    29.         //$this->xml->addChild('item', $value)->addAttribute('name', $key);
    30.     }
    31.  
    32.     public function write(){
    33.         file_put_contents($this->file, $this->xml->asXML());
    34.     }
    35. }
    Обратил внимание что свойства $this->xml изменяются так же как мы изменяем свойства $this->lastmatch, они оба экземпляры класса SimpleXMLElement, но разные ($this->lastmatch не является ссылкой на $this->xml, у них разные идентификаторы), так каким образом они так взаимодействуют?

    P.S. Так же обратил внимание что к этим объектам можно обращаться как к массивам ($this->xml[0]), что как раз меняет их идентификаторы иногда.
     
  2. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    $this->xml результат возврата функции simplexml_load_file
    $this->lastmatch результат метода $this->xml->xpath с первым аргументом /conf/item[@name="$str"]

    значит читай что за simplexml_load_file и $this->xml->xpath возвращают и в каком формате
    https://php.ru/manual/function.simplexml-load-file.html
    https://php.ru/manual/simplexmlelement.xpath.html
     
  3. yuri

    yuri Активный пользователь

    С нами с:
    16 янв 2012
    Сообщения:
    288
    Симпатии:
    2
  4. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Да, я знаю что они оба объекты класса SimpleXMLElement, но ведь это два разных экземпляра, не так ли? почему изменение свойств одного из них меняют и второй?
     
  5. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    У Зандстре не написано, что объекты в переменных хранятся по ссылке?
    PHP:
    1. class A {public $b = 5};
    2.  
    3. $a = new A;
    4. $b = $a;
    5.  
    6. $b->b = 6;
    7. echo $a->b; // Выведет 6, поскольку переменные $a и $b ссылаются на один объект
     
  6. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    PHP:
    1. class cls {
    2.     var $xxx;
    3. }
    4.  
    5. function get_cls() {
    6.     return new cls();
    7. }
    но ведь в данном случае get_cls() возвращает не один и тот же экземпляр объекта, а разные? а simplexml_load_file возвращает один и тот же.
    автар спрашивает за это.
     
  7. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Код (Text):
    1. <?php
    2. echo "<pre>";
    3. $string = <<<XML
    4. <a>
    5. <b>
    6.   <c>текст</c>
    7.   <c>вещь</c>
    8. </b>
    9. <d>
    10.   <c>код</c>
    11. </d>
    12. </a>
    13. XML;
    14.  
    15. $xml = new SimpleXMLElement($string);
    16.  
    17.  
    18. $result = $xml->xpath('/a/d');
    19.  
    20. $result[0]->c = 'one';
    21.  
    22. var_export($result);
    23. echo "<hr>";
    24. var_export($xml);
    xpath возвращает массив с ссылками на элементы которые попали под условие.
    по этому изменяя в $result ты меняешь то что в $xml.
    https://php.ru/manual/language.references.html
     
    Overfinch нравится это.
  8. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    но наличие тут разных идентификаторов, не указывает на то что это разные экземпляры?

    var_dump($this->lastmatch[0]);
    Код (Text):
    1. object(SimpleXMLElement)#4 (2) {
    2.   ["@attributes"]=>
    3.   array(1) {
    4.     ["name"]=>
    5.     string(3) "new"
    6.   }
    7.   [0]=>
    8.   string(1) "2"
    9. }
    var_dump($this->xml);
    Код (Text):
    1. object(SimpleXMLElement)#2 (1) {
    2.   ["item"]=>
    3.   array(5) {
    4.     [0]=>
    5.     string(3) "Bob"
    6.     [1]=>
    7.     string(7) "newpass"
    8.     [2]=>
    9.     string(9) "localhost"
    10.     [3]=>
    11.     string(1) "1"
    12.     [4]=>
    13.     string(1) "2"
    14.   }
    15. }
     
  9. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    какие разные идентификаторы?
     
  10. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    object(SimpleXMLElement)#4
    object(SimpleXMLElement)#2

    4 и 2

    Разве это не означает что это разные экземпляры?
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Походу ты из тех несгибаемых людей, которых ничто не может переубедить, даже сама реальность им не указ.
     
  12. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Нет, я просто хочу понять как, так происходит, в документации написано что xpath Возвращает массив объектов SimpleXMLElement, но не сказано что это ссылки на тот же экземпляр, я так понял что он как-то возвращает ссылку только на свойство самого объекта? или не так?
     
  13. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Из твоего описания симптомов я делаю вывод, что
    1) у тебя есть ссылки на один и тот же объект.
    2) твоё предположение насчёт значков имяКласса#х оказалось неверным.
    Вникать и перепроверять ломает, тем более я с телефона.
    --- Добавлено ---
    Я так понимаю, что объекты разные, но их свойства указывают на одни и те же "дочерние" ветви большого дерева. Вот это видимо сбивает тебя с толку.
     
  14. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Если не сложно, подскажите как можно вернуть ссылку на свойство объекта, а не на весь объект? Примерно так как это делает xpath в данном случае?
    P.S. https://php.ru/manual/language.references.arent.html - прочел, ничего про это не нашлось
     
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Да запросто. Если $a->b это объект, то присваивая например так:
    $x->z = $a->b
    ты копируешь ссылку, а не создаёшь новый объект. Непонятно?
    --- Добавлено ---
    Сейчас x и a это разные объекты. Но у них некоторые свойства общие.
     
  16. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Я так понял вы имели ввиду присвоить ссылку на свойство так?
    $x->z =& $a->b;
     
  17. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Я имел в виду буквально то, что сказал. Объекты присваиваются по ссылке. Им не нужен значёк & для этого.
    --- Добавлено ---
    Сейчас понял?
     
  18. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    На сколько я понял, если что-то является ссылкой, то var_dump() покажет что это ссылка, и выведет & перед значением, или я не прав?
     
  19. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Код (PHP):
    1. $a = new stdClass();
    2. $a->foo = new stdClass();
    3. $a->foo->bar = 123;
    4.  
    5. $x = new stdClass();
    6. $x->z = $a->foo;
    7. $x->z->bar = 456;
    8.  
    9. echo $a->foo->bar; // что выведет?
    --- Добавлено ---
    А у тебя много интересных мыслей! Попробуй — узнаешь. Обычно ты неправ.
     
    Overfinch нравится это.
  20. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Это я понимаю, там явно видно что они оба ссылаются на один и тот же объект
    object(stdClass)#2 (1) {
    ["bar"]=>
    int(456)
    }
    в моём случае они вроде разные.
    Подскажите как можно, не в ручную, а именно методом вернуть ссылку на свойство, как это делает xpath.
     
  21. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    чо?
    --- Добавлено ---
    я думаю, ты слишком умый чтобы стать программистом. ты просто делай, не надо всё подвергать соменнию и анализу.
    --- Добавлено ---
    чтобы сделать как xpath, надо вызвать xpath. он всё ништяк делает.
     
  22. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Ну SimpleXMLElement::xpath() возвращает массив с объектами, изменяя свойства этих объектов, мы изменяем свойства объекта, который вернул simplexml_load_file(), то есть xpath() вернул объекты с ссылками на свойства другого объекта?
     
  23. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Знаешь, всегда найдется способ всё испортить. Нет 100% bullet proof технологии.
    Сейчас ты знаешь об этой тонкости с simplexml, вероятность косяка вроде снизилась, не?

    Чтобы не перезатереть свойство объекта не перезатирай его.
     
    Overfinch нравится это.
  24. Overfinch

    Overfinch Новичок

    С нами с:
    10 май 2016
    Сообщения:
    11
    Симпатии:
    0
    Понял, спасибо.
     
  25. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Тема себя исчерпала, я считаю. Уже не смешно.