This question already has answers here:
PHP param by ref => assign to ref = NULL
(1 answer)
PHP's assignment by reference is not working as expected
(7 answers)
Closed 8 years ago.
Here is the simplified version of code that might be revealing a PHP bug
class AClass
{
public static $prop = "Hi";
}
function assignRef (&$ref)
{
$ref = &AClass::$prop;
echo "inside assignRef: $ref\n";
}
$ref = "Hello";
assignRef($ref);
echo "outside: $ref\n";
This prints out
inside assignRef: Hi
outside: Hello
Shouldn't $ref had been assigned by reference to $prop static variable of the AClass class and become "Hi" not just inside assignRef function but also outside of it?
The class in your example is irrelevant, simplified version that produces the same output:
function assignRef (&$ref)
{
$prop = 'Hi';
$ref = &$prop;
echo "inside assignRef: $ref\n";
}
$ref = "Hello";
assignRef($ref);
echo "outside: $ref\n";
What is happening is that when assigning by reference inside the function ($ref = &$prop;) you are just changing what one variable is pointing to, not changing the value of what it was originally pointing to nor changing any other references to that original value.
You effectively have two variables called $ref in this example - one inside the function, and one outside the function. You are changing what the variable inside the function points to, leaving the other variable pointing to the original (unchanged) value.
Consider the following code:
$a = 'a';
$b = 'b';
$c = 'c';
$a = &$b;
$b = &$c;
echo "$a / $b / $c";
This results in output of b / c / c, rather than what you might expect c / c / c. This happens for the same reason - assignment by reference does not affect the value originally referenced nor change any other references, meaning any other variables pointing to the original value are unchanged.
If you want to change the value, rather than creating a new reference to another value, you must use normal assignment (=). Alternatively, you could change all references.
Related
I have seen in my journey to creaitng and building some of my php applications, the & symbol within front of vars, = and class names.
I understand that these are PHP References, but the docs i have seen and looked at seem to just not explain it in a way that i understand or confusing. How can you explain the following examples that i have seen to make them more understandable.
public static function &function_name(){...}
$varname =& functioncall();
function ($var, &$var2, $var3){...}
Much appreciated
Let's say you have two functions
$a = 5;
function withReference(&$a) {
$a++;
}
function withoutReference($a) {
$a++;
}
withoutReference($a);
// $a is still 5, since your function had a local copy of $a
var_dump($a);
withReference($a);
// $a is now 6, you changed $a outside of function scope
var_dump($a);
So, passing argument by reference allows function to modify it outside of the function scope.
Now second example.
You have a function which returns a reference
class References {
public $a = 5;
public function &getA() {
return $this->a;
}
}
$references = new References;
// let's do regular assignment
$a = $references->getA();
$a++;
// you get 5, $a++ had no effect on $a from the class
var_dump($references->getA());
// now let's do reference assignment
$a = &$references->getA();
$a++;
// $a is the same as $reference->a, so now you will get 6
var_dump($references->getA());
// a little bit different
$references->a++;
// since $a is the same as $reference->a, you will get 7
var_dump($a);
Reference functions
$name = 'alfa';
$address = 'street';
//declaring the function with the $ tells PHP that the function will
//return the reference to the value, and not the value itself
function &function_name($what){
//we need to access some previous declared variables
GLOBAL $name,$address;//or at function declaration (use) keyword
if ($what == 'name')
return $name;
else
return $address;
}
//now we "link" the $search variable and the $name one with the same value
$search =& function_name('name');
//we can use the result as value, not as reference too
$other_search = function_name('name');
//any change on this reference will affect the "$name" too
$search = 'new_name';
var_dump($search,$name,$other_search);
//will output string 'new_name' (length=8)string 'new_name' (length=8)string 'alfa' (length=4)
Usually you use the method with Objects that implemented the same interface, and you want to choose the object you want to work with next.
Passing by reference:
function ($var, &$var2, $var3){...}
I'm sure you saw the examples, so I'll just explain how and when to use it.
The basic scenario is when do you have a big logic that you want to apply to a current object/data, and you do not wish to make more copies of it (in memory).
Hope this helps.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reference - What does this symbol mean in PHP?
what is the meaning of &$variable
and meaning of functions like
function &SelectLimit( $sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0 )
{
$rs =& $this->do_query( $sql, $offset, $nrows, $inputarr);
return $rs;
}
Passing an argument like so: myFunc(&$var); means that the variable is passed by reference (and not by value). So any modifications made to the variable in the function modify the variable where the call is made.
Putting & before the function name means "return by reference". This is a bit very counter-intuitive. I would avoid using it if possible. What does it mean to start a PHP function with an ampersand?
Be careful not to confuse it with the &= or & operator, which is completely different.
Quick test for passing by reference:
<?php
class myClass {
public $var;
}
function incrementVar($a) {
$a++;
}
function incrementVarRef(&$a) { // not deprecated
$a++;
}
function incrementObj($obj) {
$obj->var++;
}
$c = new myClass();
$c->var = 1;
$a = 1; incrementVar($a); echo "test1 $a\n";
$a = 1; incrementVar(&$a); echo "test2 $a\n"; // deprecated
$a = 1; incrementVarRef($a); echo "test3 $a\n";
incrementObj($c); echo "test4 $c->var\n";// notice that objects are
// always passed by reference
Output:
Deprecated: Call-time pass-by-reference has been deprecated; If you would like
to pass it by reference, modify the declaration of incrementVar(). [...]
test1 1
test2 2
test3 2
test4 2
The ampersand - "&" - is used to designate the address of a variable, instead of it's value. We call this "pass by reference".
So, "&$variable" is the reference to the variable, not it's value. And "function &func(..." tells the function to return the reference of the return variable, instead of a copy of the variable.
See also:
difference between function and &function
http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference
http://www.php.net/manual/en/language.references.pass.php
http://www.adp-gmbh.ch/php/pass_by_reference.html
I have a simple question here. Is there a difference between passing a variable by reference in a function parameter like:
function do_stuff(&$a)
{
// do stuff here...
}
and do it inside the function like:
function do_stuff($a)
{
$var = &$a;
// do stuff here...
}
What are the differences (if any) between using these two?. Also, can anybody give me a good tutorial that explains passing by reference? I can't seem to grasp this concept 100%.
Thank you
Here's a set of examples so you can see what happens with each of your questions.
I also added a third function which combines both of your questions because it will also produce a different result.
function do_stuff(&$a)
{
$a = 5;
}
function do_stuff2($a)
{
$var = &$a;
$var = 3;
}
function do_stuff3(&$a)
{
$var = &$a;
$var = 3;
}
$a = 2;
do_stuff($a);
echo $a;
echo '<br />';
$a = 2;
do_stuff2($a);
echo $a;
echo '<br />';
$a = 2;
do_stuff3($a);
echo $a;
echo '<br />';
They're not at all equivalent. In the second version, you're creating a reference to an undefined variable $a, causing $var to point to that same null value. Anything you do to $var and $a inside the second version will not affect anything outside of the function.
In the first version, if you change $a inside the function, the new value will be present outside after the function returns.
In your first example, if you modify $a inside the function in any way, the original value outside the function will be modified as well.
In your second example, whatever you do to $a or its reference $var will not modify the original value outside the function.
In the second function, the $a passed into the function is a copy of the argument passed in, (unless $a is an object), so you are making a $var a reference to the $a inside the function but it will still be separate from the variable passed to the function.
Assuming you are using a recent version of PHP, objects are automatically passed by reference too, so that could make a difference.
I am following class based coding for project development.I have recently seen that some times we put "&" ahead of function name..
for an example..
rather than defining
function test()
it is defined like
function &test()
is there any special meaning of "&"?
As #philip mentions, it is to return a reference:
From the above link:
Note: Unlike parameter passing, here you have to use & in both places - to indicate that you want to return by reference, not a copy, and to indicate that reference binding, rather than usual assignment, should be done for $myValue.
PHP stores every variable in a ZVAL container.
From the above link:
A zval container contains, besides the variable's type and value, two additional bits of information.The first is called "is_ref" and is a boolean value indicating whether or not the variable is part of a "reference set". With this bit, PHP's engine knows how to differentiate between normal variables and references. Since PHP allows user-land references, as created by the & operator, a zval container also has an internal reference counting mechanism to optimize memory usage. This second piece of additional information, called "refcount", contains how many variable names (also called symbols) point to this one zval container.
Observe the values of variable in the output:
Consider the following without & at the assignment of return value:
$b=0;
function &func ($name) {
global $b;
$b = 10;
return $b;
}
$a = func("myname");// no & at assignment
++$a ;
echo '<br/>$a= '.$a.' $b= ' .$b."<br/>";
xdebug_debug_zval('a'); echo "<br/>";
The output for the above code:
$a= 11 $b= 10
a: (refcount=1, is_ref=0)=11
Although the function returns by reference, the reference is for the returned value's zval container. Now, when we are trying to assign the returned value, (say without a & at the assignment) only the "refcount" will increase. Where as the "is_ref" will not be altered. When the 'variable in which the returned value is stored', is tried to alter, a C.O.W (copy on write) takes place and a new zval container is created rendering the return by reference useless. Hence you will need to add the & at the assignment of the return value as well.
Consider the following with & at the assignment of return value:
$b=0;
function &func ($name) {
global $b;
$b = 10;
return $b;
}
$a =& func("myname");// & at assignment
++$a ;
echo '<br/>$a= '.$a.' $b= ' .$b."<br/>";
xdebug_debug_zval('a'); echo "<br/>";
The output:
$a= 11 $b= 11
a: (refcount=2, is_ref=1)=11
pass by reference and return reference
This means that the function returns a reference to a variable.
You can read more about it here: http://php.net/manual/en/language.references.php
Please see this code:
function addCounter(&$userInfoArray) {
$userInfoArray['counter']++;
return $userInfoArray['counter'];
}
$userInfoArray = array('id' => 'foo', 'name' => 'fooName', 'counter' => 10);
$nowCounter = addCounter($userInfoArray);
echo($userInfoArray['counter']);
This will show 11.
But! If you remove "&"operator in the function parameter, the result will be 10.
What's going on?
The & operator tells PHP not to copy the array when passing it to the function. Instead, a reference to the array is passed into the function, thus the function modifies the original array instead of a copy.
Just look at this minimal example:
<?php
function foo($a) { $a++; }
function bar(&$a) { $a++; }
$x = 1;
foo($x);
echo "$x\n";
bar($x);
echo "$x\n";
?>
Here, the output is:
1
2
– the call to foo didn’t modify $x. The call to bar, on the other hand, did.
Here the & character means that the variable is passed by reference, instead of by value. The difference between the two is that if you pass by reference, any changes made to the variable are made to the original also.
function do_a_thing_v ($a) {
$a = $a + 1;
}
$x = 5;
do_a_thing_v($x);
echo $x; // echoes 5
function do_a_thing_r (&$a) {
$a = $a + 1;
}
$x = 5;
do_a_thing_v($x);
echo $x; // echoes 6
When using the ampersand prior to a variable in a function call, it associates with the original variable itself. With that, the code you posted is saying that it will add 1 to the counter of the original array. Without the ampersand, it takes a copy of the data and adds to it, then returns the new counter of 11. The old array still remains intact at 10 and the new counter variable returned turns into 11.
http://www.phpreferencebook.com/samples/php-pass-by-reference/
is a good example.
Maybe I can add to the other answers that, if it is an object, then it is not "the object passed as value", but it is "the object's reference is passed as a value" (although I am asking what the difference is between "the object is passed by reference" vs "the object's reference is passed by value" in the comments). An array is passed by value by default.
Information: Objects and references
Example:
class Foo {
public $a = 10;
}
function add($obj) {
$obj->a++;
}
$foo = new Foo();
echo $foo->a, "\n";
add($foo);
echo $foo->a, "\n";
Result:
$ php try.php
10
11