Difference between revisions of "PHP/referencing"
| (12 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| − | In PHP, a variable can be accessed either by ''value'' or by ''reference''. All PHP variables are references; the question is what you're accessing – the location of the value or what's stored there. By default, you're accessing the value; referencing syntax allows you to refer to the location instead. | + | In PHP, a variable can be accessed either by ''value'' or by ''reference''. All PHP variables are references; the question is what you're accessing – the location of the value or what's stored there. By default, you're accessing the value; referencing syntax allows you to refer to the location instead. Unlike with a pointer, however, the location's address is never accessible to PHP code; it can only be copied. |
==Concepts== | ==Concepts== | ||
Each variable in PHP is a reference to a storage location; the details of this are generally hidden. When one variable is assigned a ''reference'' to another (rather than just the value) they then ''both refer to the same storage location''. This storage location will continue to exist as long as at least one variable is using it. | Each variable in PHP is a reference to a storage location; the details of this are generally hidden. When one variable is assigned a ''reference'' to another (rather than just the value) they then ''both refer to the same storage location''. This storage location will continue to exist as long as at least one variable is using it. | ||
| − | References do allow some of the functionality provided by pointers in other languages (like C/C++), but unlike pointers they are de-referenced | + | References do allow some of the functionality provided by pointers in other languages (like C/C++), but unlike pointers they are always de-referenced from the standpoint of the PHP code. A better analogy (the PHP manual [https://www.php.net/manual/en/language.references.whatare.php agrees]) is to think of them like hard file links in Unix. Conceptually, <code>$b = &$a</code> means "$b and $a now point to the same content", ''not'' "$b is a pointer to $a's content". |
| + | |||
| + | '''A better cognitive model''', perhaps, is to think of "<code>=</code>" and "<code>=&</code>" as what they look like — different operations: | ||
| + | * <code>$A = $B</code> copies $B's '''holder contents''' to $A, so $A and $B have the same value. | ||
| + | * <code>$A =& $B</code> copies $B's '''holder address''' to $A, so $A and $B use the same value-holder. | ||
| + | |||
| + | '''Yet another way to look at it:''' If you think of ''all'' variables in PHP as being {{l/wp|Pointer (computer programming)|pointers}}, then <code>=&</code> is the only operator which acts directly on the address in each pointer variable; all the others automatically dereference any variables they touch. | ||
| + | * Given this, referring to the <code>&</code> syntax as "referencing" is actually kind of backwards; it would be more accurately called "dereferencing". | ||
| + | |||
==Clarification== | ==Clarification== | ||
There are no reference ''types'' (you can't declare, for example, <code>&array</code> or <code>&int</code> variables or return values); there are only reference ''operations'' -- and the reference operation is basically a qualifier (indicated by <code>&</code>) on a variable-access. | There are no reference ''types'' (you can't declare, for example, <code>&array</code> or <code>&int</code> variables or return values); there are only reference ''operations'' -- and the reference operation is basically a qualifier (indicated by <code>&</code>) on a variable-access. | ||
| + | |||
| + | This is seemingly at odds with the fact that functions which return references are declared using the "&" prefix on the ''function name'' rather than on the ''return variable'', but if you think of "return" as a function which returns a reference whenever one is available (i.e. when returning a variable) and only reverts to returning a value when that's all it's got, then it makes more sense. The function having returned a reference, you want to be sure to capture that (and not just the value) by using <code>=&</code>. | ||
| + | ===correct=== | ||
| + | * <syntaxhighlight lang=php inline>$w =& $v;</syntaxhighlight>// after this line, setting $v or $w now sets the other too – because they're both using the same memory-space | ||
| + | * <syntaxhighlight lang=php inline>function &Ref(&$a) { $b=$a; return $b; }</syntaxhighlight>// Ref() returns a reference to whatever variable is passed as $a | ||
| + | * <syntaxhighlight lang=php inline>$y =& Ref($x);</syntaxhighlight>// after this line, setting $x or $y now sets the other too – because they're both using the same memory-space | ||
| + | |||
| + | ===wrong=== | ||
| + | * <code>function <span style="color:red;">R</span>ef(&$a) { $b=$a; return $b; }</code> - missing "&" before "Ref" | ||
| + | * <code>function &Ref(<span style="color:red;">$</span>a) { $b=$a; return $b; }</code> - missing "&" before "$a" | ||
| + | * <code>function &Ref(&$a) { $b=$a; return <span style="color:red;">&</span>$b; }</code> - extra "&" after "return" | ||
| + | |||
==Basics== | ==Basics== | ||
| − | To | + | To copy (assign) a reference instead of a value, use the <code>&</code> operator when referring to the source variable: |
<syntaxhighlight lang=php> | <syntaxhighlight lang=php> | ||
$vtest = 'test value'; | $vtest = 'test value'; | ||
| Line 33: | Line 53: | ||
* Writing a value to a variable that contains a reference overwrites the value of the reference target, rather than replacing the reference. | * Writing a value to a variable that contains a reference overwrites the value of the reference target, rather than replacing the reference. | ||
** This is kind of essential to how references work: spooky action at a distance, basically. | ** This is kind of essential to how references work: spooky action at a distance, basically. | ||
| − | ** This also implies that the only way to change a reference-holding variable directly is to assign it a new reference or <code>unset()</code> it. | + | ** <s>This also implies that the only way to change a reference-holding variable directly is to assign it a new reference or <code>unset()</code> it.</s> |
| + | *** Actually, I think if you use <code>=&</code>, that should update the reference? To be checked. | ||
| + | |||
==Links== | ==Links== | ||
* [https://www.php.net/manual/en/language.references.php References Explained] | * [https://www.php.net/manual/en/language.references.php References Explained] | ||
Latest revision as of 00:22, 21 November 2025
In PHP, a variable can be accessed either by value or by reference. All PHP variables are references; the question is what you're accessing – the location of the value or what's stored there. By default, you're accessing the value; referencing syntax allows you to refer to the location instead. Unlike with a pointer, however, the location's address is never accessible to PHP code; it can only be copied.
Concepts
Each variable in PHP is a reference to a storage location; the details of this are generally hidden. When one variable is assigned a reference to another (rather than just the value) they then both refer to the same storage location. This storage location will continue to exist as long as at least one variable is using it.
References do allow some of the functionality provided by pointers in other languages (like C/C++), but unlike pointers they are always de-referenced from the standpoint of the PHP code. A better analogy (the PHP manual agrees) is to think of them like hard file links in Unix. Conceptually, $b = &$a means "$b and $a now point to the same content", not "$b is a pointer to $a's content".
A better cognitive model, perhaps, is to think of "=" and "=&" as what they look like — different operations:
$A = $Bcopies $B's holder contents to $A, so $A and $B have the same value.$A =& $Bcopies $B's holder address to $A, so $A and $B use the same value-holder.
Yet another way to look at it: If you think of all variables in PHP as being pointers, then =& is the only operator which acts directly on the address in each pointer variable; all the others automatically dereference any variables they touch.
- Given this, referring to the
&syntax as "referencing" is actually kind of backwards; it would be more accurately called "dereferencing".
Clarification
There are no reference types (you can't declare, for example, &array or &int variables or return values); there are only reference operations -- and the reference operation is basically a qualifier (indicated by &) on a variable-access.
This is seemingly at odds with the fact that functions which return references are declared using the "&" prefix on the function name rather than on the return variable, but if you think of "return" as a function which returns a reference whenever one is available (i.e. when returning a variable) and only reverts to returning a value when that's all it's got, then it makes more sense. The function having returned a reference, you want to be sure to capture that (and not just the value) by using =&.
correct
$w =& $v;// after this line, setting $v or $w now sets the other too – because they're both using the same memory-spacefunction &Ref(&$a) { $b=$a; return $b; }// Ref() returns a reference to whatever variable is passed as $a$y =& Ref($x);// after this line, setting $x or $y now sets the other too – because they're both using the same memory-space
wrong
function Ref(&$a) { $b=$a; return $b; }- missing "&" before "Ref"function &Ref($a) { $b=$a; return $b; }- missing "&" before "$a"function &Ref(&$a) { $b=$a; return &$b; }- extra "&" after "return"
Basics
To copy (assign) a reference instead of a value, use the & operator when referring to the source variable:
$vtest = 'test value';
$vref = &$vtest;
echo "VTEST: ";
var_dump($vtest);
echo '<br>';
echo "VREF: ";
var_dump($vref);
echo '<br>';
$vref = 'another test';
echo "VTEST: ";
var_dump($vtest);
echo '<br>';
Output:
VTEST: string(10) "test value"
VREF: string(10) "test value"
VTEST: string(12) "another test"
This illustrates some key points:
- The
var_dump()function can't tell the difference between a variable that was given a reference and one that was given a value.- ...because there isn't one, actually.
- Writing a value to a variable that contains a reference overwrites the value of the reference target, rather than replacing the reference.
- This is kind of essential to how references work: spooky action at a distance, basically.
This also implies that the only way to change a reference-holding variable directly is to assign it a new reference orunset()it.- Actually, I think if you use
=&, that should update the reference? To be checked.
- Actually, I think if you use
Links
- References Explained
- Assignment Operators: Assignment by Reference
- Function arguments: Passing arguments by reference
- Returning values: see "Example #3 Returning a reference from a function"
- Objects and references: they're not handled quite the same
- short explanation: objects are looked up in a different table from references