Как предавате обекти по препратка в PHP 5?

В PHP 5 изисква ли се да използвате модификатора & за предаване по референция? Например,

class People() { }
$p = new People();
function one($a) { $a = null; }
function two(&$a) { $a = null; )

В PHP4 се нуждаехте от модификатора &, за да поддържате препратка след направена промяна, но съм объркан от темите, които прочетох относно автоматичното използване на PHP5 за преминаване по препратка, освен когато изрично клонира обекта.

В PHP5 модификаторът & изисква ли се да предава по референция за всички типове обекти (променливи, класове, масиви, ...)?


person Brian Graham    schedule 17.02.2012    source източник
comment
Ръководството ще реши всичките ви проблеми. php.net/manual/en/language.oop5.references.php   -  person rdlowrey    schedule 17.02.2012


Отговори (3)


изисква ли се да използвате модификатора & за предаване по препратка?

Технически/семантично отговорът еда, дори и с обекти. Това е така, защото има два начина за предаване/присвояване на обект: чрез препратка или чрез идентификатор. Когато декларация на функция съдържа &, както в:

function func(&$obj) {}

Аргументът ще бъде предаден чрез препратка, независимо от всичко. Ако декларирате без &

function func($obj) {}

Всичко ще бъде предадено по стойност, с изключение на обекти и ресурси, които след това ще бъдат предадени чрез идентификатор. Какво е идентификатор? Е, можете да мислите за това като препратка към препратка. Вземете следния пример:

class A
{
    public $v = 1;
}

function change($obj)
{
    $obj->v = 2;
}

function makezero($obj)
{
    $obj = 0;
}

$a = new A();

change($a);

var_dump($a); 

/* 
output:

object(A)#1 (1) {
  ["v"]=>
  int(2)
}

*/

makezero($a);

var_dump($a);

/* 
output (same as before):

object(A)#1 (1) {
  ["v"]=>
  int(2)
}

*/

Така че защо $a внезапно не стане цяло число, след като го предаде на makezero? Това е така, защото презаписахме само идентификатора. Ако бяхме преминали през препратка:

function makezero(&$obj)
{
    $obj = 0;
}

makezero($a);

var_dump($a);

/* 
output:

int(0) 

*/

Сега $a е цяло число. И така, има разлика между предаване чрез идентификатор и предаване през препратка.

person webbiedave    schedule 17.02.2012
comment
Благодаря ви, че обяснихте разликата между идентификатори и препратки, ръководството не беше много ясно по този въпрос. - person Brian Graham; 17.02.2012
comment
Ето как обектите на javascript се предават и по подразбиране. - person Alex_Nabu; 25.07.2015
comment
Съжаляваме, но бихте ли изяснили защо change() работи, а не makezero()? Липсва ли ви & sign in change()? Също така мисля, че в makezero искате да промените $obj = 0; към $obj-›v = 0 - person Andrew; 07.10.2016
comment
За да обобщя и сортирам всичко това в главата си: всичко, което не е обект или ресурс, се предава по стойност, освен ако не е изрично посочено с &, нали? Обектите и ресурсите се предават по идентификатор по подразбиране. И можем да мислим за идентификатор като за синоним на псевдоним, нали? Псевдонимът може да се използва за манипулиране на обекта, но той НЕ е обектът. - person Ignacio Segura; 10.11.2016

Обектите ще преминават по препратка. Вградените типове ще бъдат предавани по стойност (копирани);

Това, което се случва зад кулисите е, че когато подадете променлива, която съдържа обект, това е препратка към обекта. Така че самата променлива се копира, но все още препраща към същия обект. Така че по същество има две променливи, но и двете сочат към един и същ обект. Промените, направени в обекти във функция, ще продължат да съществуват.

В случай на кода, който имате там (първо имате нужда от $ дори с &):

$original = new Object();

one($original); //$original unaffected
two($original); //$original will now be null

function one($a) { $a = null; } //This one has no impact on your original variable, it will still point to the object

function two(&$a) { $a = null; ) //This one will set your original variable to null, you'll lose the reference to the object.
person Chris    schedule 17.02.2012
comment
Така че целите числа, низовете, символите и булевите стойности се предават по стойност, освен ако не използвате модификатора &? - person Brian Graham; 17.02.2012
comment
@BrianGraham да. Ако сте запознати с указателите в C/C++, $original в предишния пример е нещо подобно. Той съдържа адрес към създадения от нас обект. Самият $original се копира, когато се предава на функция one($a), но тъй като съдържа адрес, копието сочи към същия обект. - person Chris; 17.02.2012
comment
Казвате, че в PHP5 обектите се предават по референция, нали? Тогава защо използвате модификатора &, за да докажете твърдението си, ако не е необходим, не ми помага да разбера въпроса си. - person Brian Graham; 17.02.2012
comment
@BrianGraham Това е техническо пояснение, можете да считате обектите за предадени по препратка, но аз излагах по-техническата работа на системата. - person Chris; 17.02.2012
comment
Обектите всъщност не се предават по референция. Равенството между променлива и обект по същество предава препратка към него. Същата операция за преминаване по стойност по време на извикване на функция, т.е. $obj=$passedObject води $obj=&passedObjects - person SoWhat; 17.02.2012
comment
@SomeshMukherjee Моето разбиране е, че $obj = $passedObject, ако зададем $obj = null, $passedObject != null. Но ако $obj = &$passedObject и зададете $obj = null, сега $passedObject == null. - person Chris; 17.02.2012
comment
Това имах предвид. Прекалявах с опростяването със знака &$. Мисля, че това, което всъщност се случва, е, че се предава копие на справката. Така че задаването на референцията на null или нещо друго просто променя обекта, който референцията идентифицира, а не самия обект - person SoWhat; 17.02.2012

Използвате го погрешно. Знакът $ е задължителен за всяка променлива. Трябва да бъде: http://php.net/manual/en/language.references.pass.php

function foo(&$a)
{
$a=null;
}


foo($a);
To return a reference, use

 function &bar($a){
$a=5;
return $a

 }

В обекти и масиви препратката към обекта се копира като формален параметър, всяка операция за равенство на два обекта е обмен на препратки.

$a=new People();
$b=$a;//equivalent to &$b=&$a roughly. That is the address of $b is the same as that of $a 

function goo($obj){
//$obj=$e(below) which essentially passes a reference of $e to $obj. For a basic datatype such as string, integer, bool, this would copy the value, but since equality between objects is anyways by references, this results in $obj as a reference to $e
}
$e=new People();
goo($e);
person SoWhat    schedule 17.02.2012
comment
Забравих знака $, съжалявам. - person Brian Graham; 17.02.2012