25

In PHP 5, are you required to use the & modifier to pass by reference? For example,

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

In PHP4 you needed the & modifier to maintain reference after a change had been made, but I'm confused on the topics I have read regarding PHP5's automatic use of pass-by-reference, except when explicity cloning the object.

In PHP5, is the & modifier required to pass by reference for all types of objects (variables, classes, arrays, ...)?

TRiG
  • 10,148
  • 7
  • 57
  • 107
Nahydrin
  • 13,197
  • 12
  • 59
  • 101
  • 3
    The manual will solve all your problems. http://php.net/manual/en/language.oop5.references.php –  Feb 17 '12 at 16:08

3 Answers3

97

are you required to use the & modifier to pass-by-reference?

Technically/semantically, the answer is yes, even with objects. This is because there are two ways to pass/assign an object: by reference or by identifier. When a function declaration contains an &, as in:

function func(&$obj) {}

The argument will be passed by reference, no matter what. If you declare without the &

function func($obj) {}

Everything will be passed by value, with the exception of objects and resources, which will then be passed via identifier. What's an identifier? Well, you can think of it as a reference to a reference. Take the following example:

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)
}

*/

So why doesn't $a suddenly become an integer after passing it to makezero? It's because we only overwrote the identifier. If we had passed by reference:

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

makezero($a);

var_dump($a);

/* 
output:

int(0) 

*/

Now $a is an integer. So, there is a difference between passing via identifier and passing via reference.

webbiedave
  • 48,414
  • 8
  • 88
  • 101
  • 13
    Thank you for explaining the difference between identifiers and references, the manual wasn't very clear on this. – Nahydrin Feb 17 '12 at 18:18
  • This is how javascript objects are passed by default as well. – Alex_Nabu Jul 25 '15 at 05:50
  • Sorry but could you clarify why did change() work and not makezero()? Are you missing a & sign in change()? Also I think in makezero you want to change $obj = 0; to $obj->v = 0 – Andrew Oct 07 '16 at 12:31
  • 1
    To summarize and sort all this in my head: everything that is not an object or a resource is passed by value unless explicitly referenced with &, right? Objects and Resources are passed by identifier by default. And we could think of "identifier" as synonym for "alias", right? The "alias" can be used to manipulate the object, but it is NOT the object. – Ignacio Segura Nov 09 '16 at 22:46
0

You're using it wrong. The $ sign is compulsory for any variable. It should be: 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

 }

In objects and arrays, a reference to the object is copied as the formal parameter, any equality operations on two objects is a reference exchange.

$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);
SoWhat
  • 5,564
  • 2
  • 28
  • 59
0

Objects will pass-by-reference. Built in types will be pass-by-value (copied);

What is happening behind the scenes is that when you pass in a variable that holds an object, it's a reference to the object. So the variable itself is copied, but it still references the same object. So, essentially there are two variable, but both are pointing to the same object. Changes made to objects inside a function will persist.

In the case of the code that you have there (first you need $ even with &):

$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.
CLo
  • 3,650
  • 3
  • 26
  • 44
  • So integers, strings, chars and booleans are pass-by-value, unless using the `&` modifier? – Nahydrin Feb 17 '12 at 16:12
  • @BrianGraham yes. If you're familiar with pointers in C/C++ $original in the previous example is kind of like that. It holds an address to the Object we created. $original itself is copied when passed into function one($a), but since it holds an address the copy is pointing at the same Object. – CLo Feb 17 '12 at 16:14
  • 1
    You say that in PHP5 objects are passed by reference, right? Then why are you using the `&` modifier to prove your point if it's not needed, it's not helping me understand my question. – Nahydrin Feb 17 '12 at 16:15
  • @BrianGraham It's a technical clarification, you can consider Objects as being passed-by-reference but I was exposing the more technical workings of the system. – CLo Feb 17 '12 at 16:17
  • 1
    Objects are not actually passed by reference. An equality between a variable and an object essentially passes a reference to it. This same pass by value operation during a function call i.e $obj=$passedObject results $obj=&passedObjects – SoWhat Feb 17 '12 at 16:20
  • 1
    @SomeshMukherjee My understanding is that $obj = $passedObject, if we set $obj = null, $passedObject != null. But if $obj = &$passedObject and you set $obj = null, now $passedObject == null. – CLo Feb 17 '12 at 16:24
  • That's what I meant. I was over simplyfying with the &$ sign. I think what actually happens is that a copy of the reference is passed. So setting the reference to null or anything else just changes the object which the reference identifies, not the object itself – SoWhat Feb 17 '12 at 16:28