Reference assignment operator in PHP, =& - php

What does the =& (equals-ampersand) assignment operator do in PHP?
Is it deprecated?

It's not deprecated and is unlikely to be. It's the standard way to, for example, make part of one array or object mirror changes made to another, instead of copying the existing data.
It's called assignment by reference, which, to quote the manual, "means that both variables end up pointing at the same data, and nothing is copied anywhere".
The only thing that is deprecated with =& is "assigning the result of new by reference" in PHP 5, which might be the source of any confusion. new is automatically assigned by reference, so & is redundant/deprecated in$o = &new C;, but not in $o = &$c;.
Since it's hard to search, note that =& (equals ampersand) is the same as = & (equals space ampersand) and is often written such that it runs into the other variable like $x = &$y['z']; or $x = &$someVar (ampersand dollar sign variable name). Example simplified from the docs:
$a = 3;
$b = &$a;
$a = 4;
print "$b"; // prints 4
Here's a handy link to a detailed section on Assign By Reference in the PHP manual. That page is part of a series on references - it's worth taking a minute to read the whole series.

It's two different operators. = is assignment as you probably know. And & means the variable should be accessed by reference rather than by value.

$x = &$y['z'];
also has the effect of creating $y['z'] if it doesn't exist, and setting it to null.
This prevents error messages that you might have wanted to read. I haven't found documentation on this yet; possibly new in 5.3, for all I know.

The symbol & is used in various ways in PHP to represent operations with "references". The PHP manual has a section titled References Explained which every PHP programmer should read.
It's important to understand that references in PHP are not a data type, like a pointer, but a concept regarding how variables work. There is therefore no single meaning of & - you should not read it as "make a reference" - it just means "something reference-y is happening here".
In particular, the syntax $a =& $b, which can also be written $a = &$b, represents assignment by reference. It binds two variables together, so that they both point at the same piece of data. Think of the & as modifying the = rather than modifying the $b.
Once you've bound two variables together in this way, they are interchangeable - you can't say that "$a points to $b" or "$b points to $a":
$a =& $b;
$a = 42;
// both $a and $b will be 42
$b = 101;
// both $a and $b will be 101
You can also link more than two variables together as references, and again it doesn't matter which of the existing names you use on the right-hand side of the assignment:
$a =& $b;
$c =& $b;
$d =& $a;
$e =& $c;
// $a, $b, $c, $d, and $e now all point to the same data, interchangeably
However, if you put the same variable on the left-hand side, it breaks the existing link of that variable, and links it to something else:
$a =& $b;
// $a and $b are linked together
$a =& $c;
// $a is now linked to $c
// the value of $b doesn't change, but it is not linked to $a or $c
To "break" the link without making a new link, you can use the unset keyword:
$a =& $b;
$c =& $a;
// $a, $b, and $c are all linked together
unset($a);
// $b and $c are still linked together, but $a is independent
Some descriptions refer to =& as "creating or adding to a reference set". Perhaps it would have been better if it had been implemented as a function, like bind($a, $b) to highlight that both arguments are affected by the operation.

I'd like to draw some attention to the semantics and code styling of "Assigning By Reference". The OP's opening sentence hints toward a misconception:
What does the =& (equals-ampersand) assignment operator do in PHP?
First, let's review the dedicated section of the PHP Docs page for Assignment Operators. Notice how the = comes before the & and that the two symbols are separated. This is because they are NOT "combined operators". Semantically, it is "assigning" a "reference"; it is not a "reference assignment operator".
Second, look at how ALL of the "combined operators" are written lower on the docs page. The = is consistently the right-most symbol. This is a very important distinction because writing the & on the left of the = changes the meaning -- it becomes a combined operator ("bitwise and assignment operator") instead of an assignment to a reference.
PSR coding standards should be something that all PHP developers are aware of and strive to obey. Notice this rule of PSR-12 Section 6.2:
All binary arithmetic, comparison, assignment, bitwise, logical, string, and type operators MUST be preceded and followed by at least one space
By this rule, there should always be a space after the = operator -- this makes =& a violation.
Furthermore, there are other rules that state that there should not be a space between & and its variable/argument/function/etc.
When using the reference operator & before an argument, there MUST NOT be a space after it
TL;DR
When assigning a reference, always write the = with spaces on both sides and never write a space after &.
Bad: $a =& $b;
Good: $a = &$b;
Demonstrated consistently/correctly: https://riptutorial.com/php/example/11991/assign-by-reference
Not demonstrated consistently/correctly:
https://www.php.net/manual/en/language.references.whatdo.php#:~:text=$a%20=%26%20$b;
https://www.php.net/manual/en/language.references.whatdo.php#:~:text=$foo%20=%26%20find_var($bar);
https://www.php.net/manual/en/language.oop5.basic.php#:~:text=$reference%20%20=%26%20$instance;

Related

Reference assignment operator ( =& ) combined with passed by reference ( &$var ) in PHP

Why is the variable passed by reference not changed when the assignment is also made with a reference?
function foo(&$x) {
$y = 1;
$x = &$y;
}
$bar = 0;
foo($bar);
echo $bar; //why is this not 1?
This behavior seems to be identical in all PHP versions. Therefore I assume that the behavior is by design.
Is it documented somewhere that the reference is lost in such cases?
References in PHP are a means to access the same variable content by different names. They are not like C pointers; for instance, you cannot perform pointer arithmetic using them, they are not actual memory addresses, and so on. [..] Instead, they are symbol table aliases. Note that in PHP, variable name and variable content are different, so the same content can have different names. The closest analogy is with Unix filenames and files - variable names are directory entries, while variable content is the file itself. References can be likened to hardlinking in Unix filesystem.
What References Are
<?php
$a =& $b;
?>
it means that $a and $b point to the same content.
Note:
$a and $b are completely equal here. $a is not pointing to $b or vice versa. $a and $b are pointing to the same place.
What References Do
So, $x = &$y; makes $x an alias of the value that $y is pointing to. If $x was an alias to some value before, that's broken now, because it can only point to one value at a time.
However, it feels wrong that you can destroy the passed by reference relationship.
Well, that's entirely up to you. If you understand how references work, then you are entirely in control of writing code that makes them work as you want them to.
A variable is a name assigned to a value. You pass or use a variable by retrieving its value and work with this or by its name for later refering to it. Passing by reference has the problem that other processes may change the variable's value while you are working with it. If you are passing by value, you give a new name to the value and have good chances that no other process will know this name and do unwanted things with the associated value.
What is not possible is to make e.g. "x" first a reference to "bar" and then "x" a reference to "y" and then expect the name "bar" to be a new name for the value of "y". In other word you first said "with x I mean bar", then "with x I mean y", and then "give me the value assigned to bar". Where should be a change of the value assigned to "bar"? It's nothing else than
$bar = 0;
$x = &$bar;
$y = 1;
$x = &$y;
echo $bar; // 0
What you expect from your function would require to explicitly "re-establish" the association between "x" and "bar" by assigning "bar" to "x":
$bar = 0;
$x = &$bar;
$y = 1;
$x = &$y;
$bar = &$x;
echo $bar; // 1
Consider that your function foo(&$x) effectively is "function foo($x = &$bar)" (of course formally not possible to state). This makes clear that you have two competing $x = &, the winning last one fully overwriting the losing first one.

PHP pass by reference difference between equals ampersand and equals space ampersand [duplicate]

What does the =& (equals-ampersand) assignment operator do in PHP?
Is it deprecated?
It's not deprecated and is unlikely to be. It's the standard way to, for example, make part of one array or object mirror changes made to another, instead of copying the existing data.
It's called assignment by reference, which, to quote the manual, "means that both variables end up pointing at the same data, and nothing is copied anywhere".
The only thing that is deprecated with =& is "assigning the result of new by reference" in PHP 5, which might be the source of any confusion. new is automatically assigned by reference, so & is redundant/deprecated in$o = &new C;, but not in $o = &$c;.
Since it's hard to search, note that =& (equals ampersand) is the same as = & (equals space ampersand) and is often written such that it runs into the other variable like $x = &$y['z']; or $x = &$someVar (ampersand dollar sign variable name). Example simplified from the docs:
$a = 3;
$b = &$a;
$a = 4;
print "$b"; // prints 4
Here's a handy link to a detailed section on Assign By Reference in the PHP manual. That page is part of a series on references - it's worth taking a minute to read the whole series.
It's two different operators. = is assignment as you probably know. And & means the variable should be accessed by reference rather than by value.
$x = &$y['z'];
also has the effect of creating $y['z'] if it doesn't exist, and setting it to null.
This prevents error messages that you might have wanted to read. I haven't found documentation on this yet; possibly new in 5.3, for all I know.
The symbol & is used in various ways in PHP to represent operations with "references". The PHP manual has a section titled References Explained which every PHP programmer should read.
It's important to understand that references in PHP are not a data type, like a pointer, but a concept regarding how variables work. There is therefore no single meaning of & - you should not read it as "make a reference" - it just means "something reference-y is happening here".
In particular, the syntax $a =& $b, which can also be written $a = &$b, represents assignment by reference. It binds two variables together, so that they both point at the same piece of data. Think of the & as modifying the = rather than modifying the $b.
Once you've bound two variables together in this way, they are interchangeable - you can't say that "$a points to $b" or "$b points to $a":
$a =& $b;
$a = 42;
// both $a and $b will be 42
$b = 101;
// both $a and $b will be 101
You can also link more than two variables together as references, and again it doesn't matter which of the existing names you use on the right-hand side of the assignment:
$a =& $b;
$c =& $b;
$d =& $a;
$e =& $c;
// $a, $b, $c, $d, and $e now all point to the same data, interchangeably
However, if you put the same variable on the left-hand side, it breaks the existing link of that variable, and links it to something else:
$a =& $b;
// $a and $b are linked together
$a =& $c;
// $a is now linked to $c
// the value of $b doesn't change, but it is not linked to $a or $c
To "break" the link without making a new link, you can use the unset keyword:
$a =& $b;
$c =& $a;
// $a, $b, and $c are all linked together
unset($a);
// $b and $c are still linked together, but $a is independent
Some descriptions refer to =& as "creating or adding to a reference set". Perhaps it would have been better if it had been implemented as a function, like bind($a, $b) to highlight that both arguments are affected by the operation.
I'd like to draw some attention to the semantics and code styling of "Assigning By Reference". The OP's opening sentence hints toward a misconception:
What does the =& (equals-ampersand) assignment operator do in PHP?
First, let's review the dedicated section of the PHP Docs page for Assignment Operators. Notice how the = comes before the & and that the two symbols are separated. This is because they are NOT "combined operators". Semantically, it is "assigning" a "reference"; it is not a "reference assignment operator".
Second, look at how ALL of the "combined operators" are written lower on the docs page. The = is consistently the right-most symbol. This is a very important distinction because writing the & on the left of the = changes the meaning -- it becomes a combined operator ("bitwise and assignment operator") instead of an assignment to a reference.
PSR coding standards should be something that all PHP developers are aware of and strive to obey. Notice this rule of PSR-12 Section 6.2:
All binary arithmetic, comparison, assignment, bitwise, logical, string, and type operators MUST be preceded and followed by at least one space
By this rule, there should always be a space after the = operator -- this makes =& a violation.
Furthermore, there are other rules that state that there should not be a space between & and its variable/argument/function/etc.
When using the reference operator & before an argument, there MUST NOT be a space after it
TL;DR
When assigning a reference, always write the = with spaces on both sides and never write a space after &.
Bad: $a =& $b;
Good: $a = &$b;
Demonstrated consistently/correctly: https://riptutorial.com/php/example/11991/assign-by-reference
Not demonstrated consistently/correctly:
https://www.php.net/manual/en/language.references.whatdo.php#:~:text=$a%20=%26%20$b;
https://www.php.net/manual/en/language.references.whatdo.php#:~:text=$foo%20=%26%20find_var($bar);
https://www.php.net/manual/en/language.oop5.basic.php#:~:text=$reference%20%20=%26%20$instance;

The object assignment doesn't make sense in PHP OOP

I was tested and I got this wrong but this doesn't make sense:
class myClass
{
public $x;
function myMethod()
{
echo $this->x;
}
}
$a = new myClass();
$a->x = 10;
$b = $a;
$b->x = 20;
$c = clone $b;
$c->x = 30;
$a->myMethod();
$b->myMethod();
$c->myMethod();
My intuition would be 102030 but the result is actually 202030!!! What happened to 10?!?! Shouldn't the variable of $a be left alone? I thought all objects are independent and would not be updated unless it has direct reference set by the ampersand (=&)?
In $b = $a;, only the object reference is being copied, not the object.
When you use clone, however, the object is indeed being copied, so $c = clone $b, creates both a new object (referenced by $c) and a new reference ($c).
In $b =& $a;, both symbols $a and $b would point to the same reference, that is, not even the reference would be copied (and therefore an assignment to $b of, say, an integer, would also affect the value of $a).
To sum up, there are two indirections here: from the symbol to the "zval" (in the case an object reference) and from the object reference to the object itself (i.e., to a portion of memory where the actual object state is stored).
From the PHP manual:
When assigning an already created instance of a class to a new variable, the new variable will access the same instance as the object that was assigned. This behaviour is the same when passing instances to a function. A copy of an already created object can be made by cloning it.
PHP uses references for objects. So when you create a new one
$a = new myClass();
PHP doesn't actually store it in $a, it just puts the reference there. Now you copy the reference:
$b = $a;
When you modify the object pointed by $a, you also modify the one pointed by $b because they point to the same thing.
As $a represents a reference to an object and not the object itself, you are assigning the reference to $b. Now, $a and $b reference the same object, when you manipulate the object referenced by $b, the changes get reflected accessing it via $a as well.
Objects are handled by reference, and references are aliases on assignment. So after you say $b = $a, both variables refer to the same object.
The value/reference distinction is fundamental in many "modern" OO languages: values are copied, references are aliased. It is perhaps unfortunate that the syntax of the language does not always make it obvious which semantics the variable obeys at any given point.

In PHP can someone explain cloning vs pointer reference?

To begin with, I understand programming and objects, but the following doesn't make much sense to me in PHP.
In PHP we use the & operator to retrieve a reference to a variable. I understand a reference as being a way to refer to the same 'thing' with a different variable. If I say for example
$b = 1;
$a =& $b;
$a = 3;
echo $b;
will output 3 because changes made to $a are the same as changes made to $b. Conversely:
$b = 1;
$a = $b;
$a = 3;
echo $b;
should output 1.
If this is the case, why is the clone keyword necessary? It seems to me that if I set
$obj_a = $obj_b then changes made to $obj_a should not affect $obj_b,
conversely $obj_a =& $obj_b should be pointing to the same object so changes made to $obj_a affect $obj_b.
However it seems in PHP that certain operations on $obj_a DO affect $obj_b even if assigned without the reference operator ($obj_a = $obj_b). This caused a frustrating problem for me today while working with DateTime objects that I eventually fixed by doing basically:
$obj_a = clone $obj_b
But most of the php code I write doesn't seem to require explicit cloning like in this case and works just fine without it. What's going on here? And why does PHP have to be so clunky??
Basically, there are two ways variables work in PHP...
For everything except objects:
Assignment is by value (meaning a copy occurs if you do $a = $b.
Reference can be achieved by doing $a = &$b (Note the reference operator operates upon the variable, not the assignment operator, since you can use it in other places)...
Copies use a copy-on-write tehnique. So if you do $a = $b, there is no memory copy of the variable. But if you then do $a = 5;, the memory is copied then and overwritten.
For objects:
Assignment is by object reference. It's not really the same as normal variable by reference (I'll explain why later).
Copy by value can be achieved by doing $a = clone $b.
Reference can be achieved by doing $a = &$b, but beware that this has nothing to do with the object. You're binding the $a variable to the $b variable. It doesn't matter if it's an object or not.
So, why is assignment for objects not really reference? What happens if you do:
$a = new stdclass();
$b = $a;
$a = 4;
What's $b? Well, it's stdclass... That's because it's not writing a reference to the variable, but to the object...
$a = new stdclass();
$a->foo = 'bar';
$b = $a;
$b->foo = 'baz';
What's $a->foo? It's baz. That's because when you did $b = $a, you are telling PHP to use the same object instance (hence the object reference). Note that $a and $b are not the same variable, but they do both reference the same object.
One way of thinking about it, is to think of all variables which store an object as storing the pointer to that object. So the object lives somewhere else. When you assign $a = $b where $b is an object, all you're doing is copying that pointer. The actual variables are still disjoint. But when you do $a = &$b, you're storing a pointer to $b inside of $a. Now, when you manipulate $a it cascades the pointer chain to the base object. When you use the clone operator, you're telling PHP to copy the existing object, and create a new one with the same state... So clone really just does a by-value copy of the varaible...
So if you noticed, I said the object is not stored in an actual variable. It's stored somewhere else and nothing but a pointer is stored in the variable. So this means that you can have (and often do have) multiple variables pointing to the same instance. For this reason, the internal object representation contains a refcount (Simply a count of the number of variables pointing to it). When an object's refcount drops to 0 (meaning that all the variables pointing to it either go out of scope, or are changed to somethign else) it is garbaged collected (as it is no longer accessable)...
You can read more on references and PHP in the docs...
Disclaimer: Some of this may be oversimplification or blurring of certain concepts. I intended this only to be a guide to how they work, and not an exact breakdown of what goes on internally...
Edit: Oh, and as for this being "clunky", I don't think it is. I think it is really useful. Otherwise you'd have variable references being passed around all over the place. And that can yield some really interesting bugs when a variable in one part of an application affects another variable in another part of the app. And not because it's passed, but because a reference was made somewhere along the line.
In general, I don't use variable references that much. It's rare that I find an honest need for them. But I do use object references all the time. I use them so much, that I'm happy that they are the default. Otherwise I'd need to write some operator (since & denotes a variable reference, there'd need to be another to denote an object reference). And considering that I rarely use clone, I'd say that 99.9% of use cases should use object references (so make the operator be used for the lower frequency cases)...
JMHO
I've also created a video explaining these differences. Check it out on YouTube.
In Short:
In PHP 5+ objects are passed by reference. In PHP 4 they are passed by value (that's why it had runtime pass by reference, which became deprecated). So, you have to use the clone operator in PHP5 to copy objects:
$objectB = clone $objectA;
Also note that it's just objects that are passed by reference, not other variables. The following may clear you up more:
PHP References
PHP Object Cloning
PHP Objects and References
i've written a presentation to explain better how php manage memory with its variables:
https://docs.google.com/presentation/d/1HAIdvSqK0owrU-uUMjwMWSD80H-2IblTlacVcBs2b0k/pub?start=false&loop=false&delayms=3000
take a look ;)

where to put & in php?

i wonder where i should put the & properly.
$b =& $a;
or
$b = &$a;
Both reference the same thing, just a matter of coding style.
Personally, I prefer the $b = &$a style for readability, the space from the & and $ throws me off.
This is actually up to you.
I would, like most others, put the & directly before the $ sign of the variable - it makes the code easier to read in my opinion.
Put it where the code convention you use tells you to put it.
The PHP manual on references uses =& exclusively, whereas the PHP manual on variables states
To assign by reference, simply prepend an ampersand (&) to the beginning of the variable which is being assigned (the source variable).

Categories