2014-02-04 3 views
0

У меня есть следующий код, который показывает, что PHP перезаписывает элементы массива объектов с последней итерацией объекта. Зачем это делать? Я хочу сохранить запись о том, что произошло с объектом, и я использую массив для этого. Посмотрите на результаты массива, когда я изменяю объект. Почему PHP это делает. Мне кажется, это может привести к серьезным ошибкам. Даже использование unset(), как рекомендовано другими, не работает. Это будет работать, только если я отключу объект ENTIRE. Но почему я хочу это сделать, если изменился только один элемент? Если у моего объекта есть 10 элементов и 1 изменение, мне нужно скопировать объект ENTIRE в массив. Причины не имеют значения, почему я должен это делать. Меня больше интересует, почему PHP имеет такое поведение. Это известная ошибка?PHP Перезаписывает элементы массива?

<?php 
$server->server = 'c17d7ae1-c298-4a1d-b7ee-2a3c9a2ab14d'; 
$servers['test1'] = $server; 

print_r($servers); 
unset($server->server); // <----- WHY DOES THIS NOT WORK? 

$server->server = 'f88043af-dcf6-4802-a3d7-91cb594da4b0'; 
$servers['test2'] = $server; 
print_r($servers); 
?> 

РЕЗУЛЬТАТЫ:

PHP test.php

Array 
(
    [test1] => stdClass Object 
     (
      [server] => c17d7ae1-c298-4a1d-b7ee-2a3c9a2ab14d 
     ) 

) 
Array 
(
    [test1] => stdClass Object 
     (
      [server] => f88043af-dcf6-4802-a3d7-91cb594da4b0 <--- This right here is WRONG 
     ) 

    [test2] => stdClass Object 
     (
      [server] => f88043af-dcf6-4802-a3d7-91cb594da4b0 
     ) 

) 
+1

"Даже при использовании снята с охраны() в соответствии с рекомендациями других" --- * рекомендованным другими за то, что *? – zerkms

+1

Вы изменяете один и тот же объект, а затем задаетесь вопросом. Вы хотите второй объект - вы создаете второй объект. – zerkms

ответ

1

Когда assiging объекты другой переменной, PHP не копирует объект, он создает ссылку. Это означает, что теперь две переменные указывают на один и тот же объект.

В вашем коде самое позднее установлено свойство server. Затем вы создаете ссылку на объект, который $server указывает на $servers[0]. Затем вы удаляете свойство server - что отлично работает. после этого вы снова устанавливаете его - в новое значение. Затем вы создадите другую ссылку в $servers[1]. Теперь у вас есть 3 переменные, указывающие на ОДИН ОБЪЕКТ: $server, $servers[0] и $servers[0].

Если вы действительно хотите сделать это таким образом (stdClass эс не должны использоваться в качестве динамических объектов, это Javascript способ сделать это и в то время как действует в PHP это противоречит ООП paradigmn), использовать clone копировать объекты :

$server->server = 'c17d7ae1-c298-4a1d-b7ee-2a3c9a2ab14d'; 
$servers['test1'] = clone $server; 
+0

Клоун - правильное исправление. Я действительно искал ответ, который бы не использовал unset, поскольку он не казался мне правильным. До сих пор я не знал о типе клонирования. – user3273074

+0

Вам вообще не нужен 'unset'. И в то время как «clone» действительно является исправлением, это не более того - вы все равно не должны делать то, что вы там делаете. –

0

Когда вы сделаете это

$servers['test1'] = $server; 

вы сохранили ссылку на $server в $servers массив на месте 'test1' , Ничто, что вы делаете с $server, не повлияет на то, что происходит со ссылкой в ​​массиве, потому что это не одно и то же. Вот что вы делаете вместо того, чтобы:

unset($servers['test1']->server); 
0

unset() сбрасывает переменная - АОТ отключив место, откуда однажды появилась переменная.

Так

$server->server = 'c17d7ae1-c298-4a1d-b7ee-2a3c9a2ab14d'; 
$servers['test1'] = $server; 

unset($server->server); //THIS DOES WORK - BUT IT IS NOT WHAT YOU WANT 
unset($servers['test1']); //NEW: THIS DOES WHAT I THINK YOU WANT 
+0

Нет, это не проблема. '$ servers-> server' и' $ servers ['server'] 'полностью эквивалентны при использовании на объектах. –

+1

Но '$ server-> server' и' $ servers ['server'] 'не являются: в конце концов есть ** s **. –

+0

Наглые имена переменных там;) Согласовано, не то же самое. Еще не то, что я хотел, чтобы OP захотела архивировать. Кажется, что цель состоит в том, чтобы иметь копию исходного значения в '$ servers [0]' после изменения '$ server-> server' –

Смежные вопросы