PHP и объекты, передача по ссылке

Lirik

Новичок
В мане есть пример http://ru2.php.net/manual/en/language.oop5.references.php, интересует эта часть, вроде значение не должно изменятся, т.к передается по ссылке(не совсем верно), но изменяется на 2
PHP:
$e = new A;
function foo($obj) {
    // ($obj) = ($e) = <id>
    $obj->foo = 2;
}
но в этом примере в статье на хабре http://habrahabr.ru/blogs/webdev/122803/#comment_4021446
PHP:
  $obj = new stdclass;
  $obj->some_property = 'lalala';
  function some_func($obj) {
      $obj = new stdclass;
  }
  function another_func_with_link(&$obj) {
      $obj = new stdclass;
  }
  some_func($obj); // $obj не изменился
  another_func_with_link($obj); // у $obj пропали все свойства
при вызове some_func, свойства не изменятся, примеры почти идентичные, почему в первом случае меняется при передаче объекта по ссылке а во втором нет?
 

Dovg

Продвинутый новичок
В первом случае ты передаешь переменную по ссылке, во втором - нет. В обоих случаях у переменной меняется значение, т.е. первоначального объекта в этой переменной уже нет.
Пример показывает не совсем то и не так, я считаю.
 

Lirik

Новичок
Dovg
чем отличается вызов function foo от function some_func ? я знаю, что такое передача по ссылке и по значению, но этот момент смутил
 

Dovg

Продвинутый новичок
В мануале же написано, что это "почти правда".

foo меняет свойства объекта, function some_func присваивает переменной другое значение. Чувствуешь разницу?
 

tz-lom

Продвинутый новичок
объекты в php5 - это ссылки изначально
что и показано в первом примере - передаётся объект как копия ссылки на структуру , потом по ссылке меняется его поле что и имеем в результате

что имеем во втором случае:
$obj это ссылка на объект , далее по ссылке задаём ей some_property
первый вызов функции:
$obj это копия , копию замещаем ,но оригинальная ссылка не меняется,поэтому и объект показывается старый
второй вызов - передаётся $obj как ссылка, т.е. в $obj ссылка на внешний $obj который ссылка на структуру объекта
когда ты ему присваиваешь значение, то ссылка аргумента разрешается и происходит подмена указателя на объект
поэтому и теряются все поля
 

Lirik

Новичок
tz-lom
т.е если бы some_property было объявлено в классе а не динамически добавилось, то оно бы изменилось?
 

tz-lom

Продвинутый новичок
почему это?
нет никакой разницы когда будет создано поле , просто если бы оно было объявлено в классе оно бы всегда создавалось при new и ему можно было бы задать доступ отличный от public
ещё раз - там не стирание поля происходит,а замена указателя на объект
если поставите var_dump то вы увидите что после 2й функции $obj уже указывает на другой объект
 

Lirik

Новичок
tz-lom
но в первом случае в мане не стоит же & в объявлении функции, значит туда тоже должна копия объекта передастся по идее?
 

tz-lom

Продвинутый новичок
ещё раз - объект это уже указатель
в первом случае копируется указатель и передаётся копия, но указывает он на ту-же структуру в памяти , а работа с полями ведётся именно через доступ к структуре по указателю,поэтому ему не важно что там не оригинальный указатель а его копия, главное что он на то же самое указывает
 

Lirik

Новичок
tz-lom
ok, но тут же тоже передается объект some_func($obj), если объект это указатель значит и тут должна передастся копия и указывает на ту же структуру не?
 

tz-lom

Продвинутый новичок
я либо уже не понимаю о чём вы, либо мы оба не понимаем о чём мы )
приведите ещё раз код о котором речь и полностью сформулируйте вопрос
 

Lirik

Новичок
tz-lom
из примера мана по ссылке http://ru2.php.net/manual/en/language.oop5.references.php, меня интересует фрагмент кода
PHP:
$e = new A;

function foo($obj) {
    // ($obj) = ($e) = <id>
    $obj->foo = 2;
}

foo($e);
echo $e->foo."\n";
тут выведет 2, но тут ничего не изменит:
PHP:
  $obj = new stdclass;
  $obj->some_property = 'lalala';
  function some_func($obj) {
      $obj = new stdclass;
  }
 some_func($obj);
 var_dump($obj);
почему? и туда и туда передается копия, только почему в первом случае меняется а во втором нет?
 

tz-lom

Продвинутый новичок
потому что $obj это копия $e , и если внутри функции заменить $obj на что то ещё то $e это не затронет
в то же время $obj это указатель на объект в памяти (как и $e) , и если пользоваться доступом к его полям,то происходит разыменовывание указателя и чтение/запись соответствующего поля структуры
изменение ссылки на объект не меняет самого объекта
из за этого есть одно простое следствие - сам объект нельзя переписать поверх (только его поля)
 

tz-lom

Продвинутый новичок

Lirik

Новичок
tz-lom
а ок, понял...что-то я затупил сильно...
MiksIr
да это то понятно...
 

MiksIr

miksir@home:~$
Что именно понятно и какой ясности не вносит? Там вполне ясно сказано, с примером, что ссылки в пхп - это совсем не указатели. По-этому изменить на что ссылается переменная, переданная как аргумент функции - нельзя.
Если уж совсем разжевывать, то представьте себе две таблицы - таблицу имен и таблицу данных.
name | data_id и data_id | data
В таблице данных лежит ваш объект под data_id = 9000, в таблице имен две записи: $bar | 9000 и $var | 9000
Как видите, работая через оба имени будете работать с одним и тем же объектом. Но во втором примере вы создаете новый объект с data_id = 9001 и апдейтите таблицу имен, так что теперь $var | 9001. Так как $var - локальная для функции, то при выходе из нее она уничтожается, т.е. уничтожается запись в таблице имен, ну и сборщик мусора уничтожает и сам объект 9001 ибо на него нет больше ссылок.
Изменить куда ссылается $bar внутри функции вы не можете, ибо вообще внутри функции ничего об этой переменной не знаете.
 
Сверху