I am trying to set a reference in a function. But, I am not able to get this working.
Code I tried:
function set(&$x, &$y)
{
$x =& $y[2];
}
$y = array(
0,
1,
array('something')
);
$x = array('old_val');
print "1. inited, x is:\n";
print_r($x);
set($x, $y);
print "\n2. now, x is: ";
print_r($x);
Output:
1. inited, x is:
Array
(
[0] => old_val
)
2. now, x is: Array
(
[0] => old_val
)
I am expecting the value of $x to be same as $y[2]. Also, any further modification to $x should change $y[2]. (As in pointer assignment in C: x = &y[2]; )
What am I doing wrong? Any suggestions appreciated.
Edit:
actually, the function set() in the test code is a simplified one for my testing purpose. It is actually select_node(&$x, &$tree, $selector) : This will select a node from the tree which matches $selector and assigns it to $x.
References aren't pointers, and act slightly differently.
What's happening is that the $x variable inside the set() function is being bound to the same location as $y[2], but $x inside set() is not the same as $x outside of set(). They both point to the same location, but you have only updated the one inside of set(), which is no longer relevant once set() returns. There is no way to bind the $x in the calling scope, as it does not exist inside the function.
See: http://ca3.php.net/manual/en/language.references.arent.php
You may want to declare set() to return a reference:
function &set(&$x, &$y) {}
And call it like this:
$x =& set($x,$y);
See http://ca3.php.net/manual/en/language.references.return.php
There is nothing wrong here. The x in function set() is a local alias to the global variable x. In other words the global x and x in function set() point to the same value. After you do this:
$x =& $y[2];
Local x now points to the value of $y[2] but the global x still points to the old value. You need to read this page http://php.net/references
Related
I saw this on W3Schools.
<?php
function myTest() {
static $x = 0;
echo $x;
$x++;
}
myTest();
myTest();
myTest();
?>
The output is 0, 1 and 2.
I wonder why it is not 0, 0 and 0.
Since each time the function is called, the variable x becomes 0 again.
I am a PHP beginner. Thanks!
If you declare a var static inside a function, the var keep it value over multiple calls. You could compare it to a static var inside of classes.
The code you post is a good example to see the actual effect. However I would only carefull use static inside functions, because most of the time, you need the static value somewhere else, reset the value, or something else which requires to much logic and makes the code really bad.
A good example would be a function, which returns a unique identifier for a given identifier. This could be simply achieved by using this code.
function unique_id($id) {
static $count = 0;
return $id . ($id++);
}
This example may clarify. static has a scope, thus is not a global variable. So I can define static $x outside the function and it will be defined there. Since static has scope, it wouldn't make any sense to keep on executing and resetting $x = 0. So, php will only acknowledge it the first time that line is called.
<?php
static $x = 1000;
function myTest() {
static $x = 0;
echo $x;
$x++;
}
myTest();
myTest();
myTest();
?>
<?php
function sum($y) {
$y = $y + 5;
}
$x = 5;
sum($x);
echo $x;
?>
So I have this code. The questions are: What does it output? The answer: 5. How do I make it to output 10? The answer: sum(&$x).
The problem is that I don't understand why the answer to the first question is 5. When you make sum($x), shouldn't it replace the function with $x, so $x= 5+5=10? Why the answer is 5? I really don't understand. Someone explaind me something related to pointers and the adress, but I didn't understand. I never understood the concept of pointers, and I googled it and apparently there are no pointers in php, so I'm super confused. My friend said that a variable is formed of a value, and the memory adress of that value. Can someone explain me like I'm 5 years old why the answer is 5 and not 10? Please
Let's pretend $x is a piece of paper with 5 written on it.
function sum($y) {
$y = $y + 5;
}
Here $y is the value of what you have written. You add 5 to such value in your mind, but the note is left untouched.
function sum(&$y) {
$y = $y + 5;
}
With the reference operator (&$y), you pass the very paper to the function, and it overwrites what's written on it.
For primitive values like numbers, I wouldn't bother and always return the value you want:
function valuePlusFive($x) {
return $x + 5;
}
$x = 5;
$x = valuePlusFive($x);
This is not a very good explanation from theory point of view, but this should help you understand the concept:
when you declare function like this and then call it:
function ($argument) {...}
The argument you pass there is passed by value. This means that inside the scope of a function you will be working with a copy of an argument you passed. You can imagine that before the function is called the copy of argument has been made and inside the function you're working with the copy, while original remains untouched. Once the function is finished the copy is no more
However when you declare it like this:
function (&$argument) {...}
You are passing argument by reference, meaning that you are working directly with a variable you've passed. So in this case no copies are made, you took the argument from one place, put it inside the function and changed it.
In PHP, "The scope of a variable is the context within which it is defined." (according to the docs). So inside your function, $y (a copy of the value you passed in) is being operated on, but it is not returned by the function. So when the function ends, the value is no longer accessible outside the function.
If you want to pass the variable in by reference (similar to a pointer in C) then you can add a & like so:
function sum(&$y) {
$y = $y + 5;
}
Now when you call this code:
$x = 5;
sum($x);
echo $x;
it will output 10. Maybe a better way to do this would be to return a value from your function, and output that value:
function sum($y) {
return $y + 5;
}
$x = 5;
echo sum($x);
I want to increase $x by 1:
$x = 1;
function addOne($x) {
$x++;
return $x;
}
$x = addOne($x);
Is there a way to do this with references, so I don't need to return $x, I can just write addOne($x)?
This is what you're looking for, a by-ref parameter indicated by &.
$x = 1;
function addOne(&$x) {
$x++;
}
addOne($x);
Some notes:
By-ref parameters require that the value passed in not be a literal. Given my example above, addOne(5) would throw a fatal exception
References are not needed for objects (including stdClass objects), as all objects are passed by reference as of PHP 5.
References ARE needed for arrays, as arrays in PHP are not treated as objects
If you want a return value of a function passed by reference, you would indicate the reference on the function name (e.g. function &foo()).
More info on references: http://php.net/manual/en/language.references.php
$x = 1;
function addOne(&$x) {
$x++;
}
addOne($x);
The & sign shows that it takes the parameter by reference. So it increments $x in the function and it will also affect the $x variable in the calling scope.
See also: http://php.net/references for a quick overview about them.
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
I have some code that appears to behave differently between PHP 4 and PHP 5. This code below:
class CFoo
{
var $arr;
function CFoo()
{
$this->arr = array();
}
function AddToArray($i)
{
$this->arr[] = $i;
}
function DoStuffOnFoo()
{
for ($i = 0; $i < 10; ++$i)
{
$foo2 = new CFoo();
$foo2 = $this; // I expect this to copy, therefore
// resetting back to the original $this
$foo2->AddToArray($i);
echo "Foo2:\n";
print_r($foo2);
echo "This:\n";
print_r($this);
}
}
}
$foo1 = new CFoo();
$foo1->DoStuffOnFoo();
Previously, in PHP 4, the assignment of $foo2 above would reset $foo2 back to the value that $this was originally set at. In this case, I would expect it to be set to a CFoo with an empty $arr member. However, the assignment of $foo2 to $this is acting as an assignment by reference. Foo2 is acting as an alias to this. Therefore when I call "AddToArray" on foo2, $this's $arr is also being appended to. So when I go to reassign foo2 back to this, instead of getting the initial value of this, I get essentially a self assignment.
Has this behavior changed in PHP 5? What can I do to force foo2 to make a copy of this?
The object-oriented part of PHP has been hugely overhauled in PHP 5. Objects are now passed (not exactly but almost) as references. See http://docs.php.net/clone.
Example:
$x1 = new StdClass;
$x1->a = 'x1a';
$x2 = $x1;
$y = clone $x1;
// Performing operations on x2 affects x1 / same underlying object
$x2->a = 'x2A';
$x2->b = 'x2B';
// y is a clone / changes do not affect x1
$y->b = 'yB';
echo 'x1: '; print_r($x1);
echo 'y:'; print_r($y);
prints
x1: stdClass Object
(
[a] => x2A
[b] => x2B
)
y:stdClass Object
(
[a] => x1a
[b] => yB
)
In PHP 4 a copy was made of an object iunless you assigned it by reference (using &=). In PHP 5 a reference to the object is assigned.
So after assigning $this to $foo2, $foo2 points to $this and not to a new copy of CFoo.
To make a copy in PHP 5 you say clone $this.
In either case, the previous new statement is wasted.
Yes, PHP 5 is now copying by reference. Now you have to clone the object to make a copy of it.
PHP has used references since version 5. To copy objects, use:
$copy = clone $object;