Доброго времени суток, изучаю ООП по Мэту Зандстре, и наткнулся на странный код: Код (Text): class Conf { private $file; private $xml; public $lastmatch; public function __construct($file){ $this->file = $file; $this->xml = simplexml_load_file($file); var_dump($this->xml[0]); } public function get($str){ $matches = $this->xml->xpath("/conf/item[@name=\"$str\"]"); if(count($matches)){ $this->lastmatch = $matches[0]; // именно когда меняем свойства этому объекту, то меняются свойства $this->xml var_dump($this->xml[0]); return (string)$matches[0]; } return null; } public function set($key,$value){ if(! is_null($this->get($key))){ $this->lastmatch[0] = $value; return; } echo "new"; //$this->xml->addChild('item', $value)->addAttribute('name', $key); } public function write(){ file_put_contents($this->file, $this->xml->asXML()); } } Обратил внимание что свойства $this->xml изменяются так же как мы изменяем свойства $this->lastmatch, они оба экземпляры класса SimpleXMLElement, но разные ($this->lastmatch не является ссылкой на $this->xml, у них разные идентификаторы), так каким образом они так взаимодействуют? P.S. Так же обратил внимание что к этим объектам можно обращаться как к массивам ($this->xml[0]), что как раз меняет их идентификаторы иногда.
$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
Возвращает объект (object) класса SimpleXMLElement https://php.ru/manual/function.simplexml-load-file.html https://php.ru/manual/simplexmlelement.xpath.html
Да, я знаю что они оба объекты класса SimpleXMLElement, но ведь это два разных экземпляра, не так ли? почему изменение свойств одного из них меняют и второй?
У Зандстре не написано, что объекты в переменных хранятся по ссылке? PHP: class A {public $b = 5}; $a = new A; $b = $a; $b->b = 6; echo $a->b; // Выведет 6, поскольку переменные $a и $b ссылаются на один объект
PHP: class cls { var $xxx; } function get_cls() { return new cls(); } но ведь в данном случае get_cls() возвращает не один и тот же экземпляр объекта, а разные? а simplexml_load_file возвращает один и тот же. автар спрашивает за это.
Код (Text): <?php echo "<pre>"; $string = <<<XML <a> <b> <c>текст</c> <c>вещь</c> </b> <d> <c>код</c> </d> </a> XML; $xml = new SimpleXMLElement($string); $result = $xml->xpath('/a/d'); $result[0]->c = 'one'; var_export($result); echo "<hr>"; var_export($xml); xpath возвращает массив с ссылками на элементы которые попали под условие. по этому изменяя в $result ты меняешь то что в $xml. https://php.ru/manual/language.references.html
но наличие тут разных идентификаторов, не указывает на то что это разные экземпляры? var_dump($this->lastmatch[0]); Код (Text): object(SimpleXMLElement)#4 (2) { ["@attributes"]=> array(1) { ["name"]=> string(3) "new" } [0]=> string(1) "2" } var_dump($this->xml); Код (Text): object(SimpleXMLElement)#2 (1) { ["item"]=> array(5) { [0]=> string(3) "Bob" [1]=> string(7) "newpass" [2]=> string(9) "localhost" [3]=> string(1) "1" [4]=> string(1) "2" } }
object(SimpleXMLElement)#4 object(SimpleXMLElement)#2 4 и 2 Разве это не означает что это разные экземпляры?
Походу ты из тех несгибаемых людей, которых ничто не может переубедить, даже сама реальность им не указ.
Нет, я просто хочу понять как, так происходит, в документации написано что xpath Возвращает массив объектов SimpleXMLElement, но не сказано что это ссылки на тот же экземпляр, я так понял что он как-то возвращает ссылку только на свойство самого объекта? или не так?
Из твоего описания симптомов я делаю вывод, что 1) у тебя есть ссылки на один и тот же объект. 2) твоё предположение насчёт значков имяКласса#х оказалось неверным. Вникать и перепроверять ломает, тем более я с телефона. --- Добавлено --- Я так понимаю, что объекты разные, но их свойства указывают на одни и те же "дочерние" ветви большого дерева. Вот это видимо сбивает тебя с толку.
Если не сложно, подскажите как можно вернуть ссылку на свойство объекта, а не на весь объект? Примерно так как это делает xpath в данном случае? P.S. https://php.ru/manual/language.references.arent.html - прочел, ничего про это не нашлось
Да запросто. Если $a->b это объект, то присваивая например так: $x->z = $a->b ты копируешь ссылку, а не создаёшь новый объект. Непонятно? --- Добавлено --- Сейчас x и a это разные объекты. Но у них некоторые свойства общие.
Я имел в виду буквально то, что сказал. Объекты присваиваются по ссылке. Им не нужен значёк & для этого. --- Добавлено --- Сейчас понял?
На сколько я понял, если что-то является ссылкой, то var_dump() покажет что это ссылка, и выведет & перед значением, или я не прав?
Код (PHP): $a = new stdClass(); $a->foo = new stdClass(); $a->foo->bar = 123; $x = new stdClass(); $x->z = $a->foo; $x->z->bar = 456; echo $a->foo->bar; // что выведет? --- Добавлено --- А у тебя много интересных мыслей! Попробуй — узнаешь. Обычно ты неправ.
Это я понимаю, там явно видно что они оба ссылаются на один и тот же объект object(stdClass)#2 (1) { ["bar"]=> int(456) } в моём случае они вроде разные. Подскажите как можно, не в ручную, а именно методом вернуть ссылку на свойство, как это делает xpath.
чо? --- Добавлено --- я думаю, ты слишком умый чтобы стать программистом. ты просто делай, не надо всё подвергать соменнию и анализу. --- Добавлено --- чтобы сделать как xpath, надо вызвать xpath. он всё ништяк делает.
Ну SimpleXMLElement::xpath() возвращает массив с объектами, изменяя свойства этих объектов, мы изменяем свойства объекта, который вернул simplexml_load_file(), то есть xpath() вернул объекты с ссылками на свойства другого объекта?
Знаешь, всегда найдется способ всё испортить. Нет 100% bullet proof технологии. Сейчас ты знаешь об этой тонкости с simplexml, вероятность косяка вроде снизилась, не? Чтобы не перезатереть свойство объекта не перезатирай его.