<?php
$x = 3;
$y = $x;
$y++;
var_dump($x); // int(3)
If it always worked that way (like in Java) that would be fine with me, but PHP has a few "wrinkles" in its variable assignment. To understand this better, you need to think of a variable name as if it were a pointer to a box. Whatever you put into the box, can be retrieved or changed by making
reference to the variable name. And in PHP you can have more than one variable name pointing to the same box.
<?php
$x = 3;
$y =& $x;
$y++;
var_dump($x); // int(4)
Could this be confusing? Yep, especially if you are used to the concept that a variable name is a
unique pointer to a variable value (the contents of the box). But that cannot be assumed. PHP permits an unlimited number of variable names to point to the same box containing the variable value.
<?php
$x = 3;
$y =& $x;
unset($y);
var_dump($x, $y); // int(3) NULL
<?php
$x = 3;
$y =& $x * 2;
var_dump($x, $y); // int(3) int(3)
$y++;
var_dump($x, $y); // int(4) int(4)
Executive Summary: Assignment statements using the equal sign produce a new box with new contents and a new variable name that points to the box. Assignment statements using the equal-ampersand produce a new variable name, but not a new box. They simply point the new variable name to the original box.
Except in
object-oriented PHP, which we will explain below.
<?php
function x(&$var)
{
$var .= ' changed';
}
$y = 'This value';
x($y);
var_dump($y); // string(18) "This value changed"
Most of the built-in PHP functions pass arguments by value. However some built-in PHP function definitions contain the ampersand! PHP
array sorting functions all work this way.
<?php
$arr = array
( 'A' => 1
, 'B' => 2
, 'C' => 3
)
;
foreach ($arr as $key => $num)
{
if ($key == 'A') unset($arr[$key]);
if ($key == 'B') $arr[$key]++;
}
print_r($arr); // Array ( [B] => 3 [C] => 3 )
It also works with objects.
<?php
$obj = new stdClass;
$obj->A = 1;
$obj->B = 2;
$obj->C = 3;
foreach ($obj as $key => $num)
{
if ($key == 'A') unset($obj->$key);
if ($key == 'B') $obj->$key++;
}
print_r($obj); // stdClass Object ( [B] => 3 [C] => 3 )
But there can be surprises if you write your foreach() statement in combination with a reference assignment! You can find an excellent explanation of this rather strange behavior on
Johannes Schleuters' blog. It has been reported as a bug repeatedly since 2004, but it is not, in fact, a bug (just a strange design element in the language). To avoid this behavior, do not use references with foreach().
<?php
$arr = array
( 'A' => 1
, 'B' => 2
, 'C' => 3
)
;
foreach ($arr as $key => &$num) { }
foreach ($arr as $key => $num) { }
print_r($arr); // Array ( [A] => 1 [B] => 2 [C] => 2 )
<?php
$arr = array
( 'A' => 1
, 'B' => 2
, 'C' => 3
)
;
$bar = $arr;
unset($bar['B']);
print_r($arr); // Array ( [A] => 1 [B] => 2 [C] => 3 )
$obj = new stdClass;
$obj->A = 1;
$obj->B = 2;
$obj->C = 3;
$bbj = $obj;
unset($bbj->B);
print_r($obj); // stdClass Object ( [A] => 1 [C] => 3 )
The object assignment contains an
implicit ampersand, creating an alias for the original object. How, then, can we get a duplicate object, one that is not a reference, but a whole new data element? There are two ways:
instantiation and
cloning.
<?php
$x = new stdClass;
$y = new stdClass;
var_dump($x, $y); // object(stdClass)#1 (0) { } object(stdClass)#2 (0) { }
As we read the var_dump() output in the snippet above, we can see that
$x is an object instance of stdClass, and it is object #1.
$y is also an object instance of stdClass, and it is object #2. Separate and identical objects -- just what we wanted.
<?php
$x = new stdClass;
$x->A = 3;
$y = clone $x;
$y->B = 4;
var_dump($x, $y); // object(stdClass)#1 (1) { ["A"]=> int(3) } object(stdClass)#2 (2) { ["A"]=> int(3) ["B"]=> int(4) }
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (3)
Commented:
If you're going to mention cloning, then I think it's beneficial to make mention of the "shallow copy" that is performed (per your "clone" link). This can be a source of confusion for new developers of any language which supports the construct.
Author
Commented:Commented:
ray paseur reference clone
and
https://www.experts-exchange.com/questions/28232255/clone-vs-reference-in-php.html?anchorAnswerId=39533264#a39533264
that this question was made for me.
I copy pasted all the code blocks because I am doing a lynda.com tutorial which uses the words reference and clone
So I am re learning all the Ray code.
Thanks.