|
|
 |
PHP references allow you to make two variables to refer to the
same content. Meaning, when you do:
it means that $a and $b
point to the same content.
Note:
$a and $b are completely
equal here, that's not $a is pointing to
$b or vice versa, that's
$a and $b pointing to the
same place.
Note:
If array with references is copied, its values are not dereferenced.
This is valid also for arrays passed by value to functions.
The same syntax can be used with functions, that return references,
and with new operator (in PHP 4.0.4 and later):
Note:
Not using the & operator causes a copy of the
object to be made. If you use $this in the class it
will operate on the current instance of the class. The assignment without
& will copy the instance (i.e. the object) and
$this will operate on the copy, which is not always
what is desired. Usually you want to have a single instance to work with,
due to performance and memory consumption issues.
While you can use the @ operator to
mute any errors in the constructor when using it as
@new, this does not work when using the
&new statement. This is a limitation of the Zend
Engine and will therefore result in a parser error.
| Warning |
If you assign a reference to a variable declared global
inside a function, the reference will be visible only inside the function.
You can avoid this by using the $GLOBALS array.
Example 21-1. Referencing global variables inside function |
<?php
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; } else {
$GLOBALS["var2"] =& $var1; }
}
global_references(false);
echo "var2 is set to '$var2'\n"; global_references(true);
echo "var2 is set to '$var2'\n"; ?>
|
|
Think about global $var; as a shortcut to $var
=& $GLOBALS['var'];. Thus assigning other reference
to $var only changes the local variable's reference.
|
Note:
If you assign a value to a variable with references in a foreach statement,
the references are modified too.
Example 21-2. References and foreach statement |
<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
}
echo $ref; ?>
|
|
| Warning |
Complex arrays are sometimes rather copied than referenced. Thus following
example will not work as expected.
Example 21-3. References with complex arrays |
<?php
$top = array(
'A' => array(),
'B' => array(
'B_b' => array(),
),
);
$top['A']['parent'] = &$top;
$top['B']['parent'] = &$top;
$top['B']['B_b']['data'] = 'test';
print_r($top['A']['parent']['B']['B_b']); ?>
|
|
|
The second thing references do is to pass variables
by-reference. This is done by making a local variable in a function and
a variable in the calling scope reference to the same content. Example:
will make $a to be 6. This happens because in
the function foo the variable
$var refers to the same content as
$a. See also more detailed explanations about passing by reference.
The third thing reference can do is return by reference.
User Contributed Notes
What References Do
ladoo at gmx dot at
17-Apr-2005 04:05
I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).
<?php
$a = 1;
$c = 2;
$b =& $a; $a =& $c; echo $a, " ", $b;
?>
miqrogroove
21-Mar-2005 03:40
More on references and globals:
String variables are not automatically passed by reference in PHP. Some other languages, such as Visual Basic, will do that automatically for all variables. PHP will not.
Consider the case where a function receives a global variable as a parameter and also has the same variable defined locally with the 'global' statement. Do the parameter and global variable now reference the same memory?
No, they do not! Passing the global variable into the function as a parameter caused a second variable to be created by default.
Here is an example of this scenario:
<?php
$teststring="Hello";
one();
function one(){
global $teststring;
two($teststring);
echo $teststring; }
function two($param){
global $teststring;
$teststring="World";
echo $param; $param="Clear?";
}
?>
Enjoy
x123 ät bestof däsh inter döt net
14-Dec-2004 04:42
It might be worth to note that a reference can be created to an unexisting variable, the reference is then "undefined" (NOT isset()) but when the other variable is created, the reference also gets "isset":
<?= phpversion(),
aa, isset($gg), bb, $a=&$GLOBALS[gg], isset($gg),cc,
isset($a),dd, $gg=ee, isset($gg),ff, isset($a),hh, $a
?>
prints
4.2.0RC2aabbccddee1ff1hhee
As I did not find anything about this "feature" in the doc, maybe better don't rely on it.
(but where the heck is this "undefined" reference living while it is not set ?)
php.devel at homelinkcs dot com
15-Nov-2004 05:16
In reply to lars at riisgaardribe dot dk,
When a variable is copied, a reference is used internally until the copy is modified. Therefore you shouldn't use references at all in your situation as it doesn't save any memory usage and increases the chance of logic bugs, as you discoved.
lars at riisgaardribe dot dk
19-Jul-2004 06:49
A comment to pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu:
The following code did not work as I expected either:
while ( $row = mysql_fetch_array( $result ) ) {
// ... do something ...
// Now store the array $row in an array containing all rows.
$result_array[] = &$row; // I dont want to copy - there is a lot of data in $row
}
var_dump ( $result_array ) shows that all stored values now are "false" as this is the last value of $row.
Instead the code should be:
while ( $row = mysql_fetch_array( $result ) ) {
// ... do something ...
$result_array[] = &$row;
unset ( $row ); //breaks the linkage between $row and a line in $result_array
}
Hope this is understandable/usefull
phpmaster a#t cybercow #se=
20-May-2004 12:15
Regarding to what "todd at nemi dot net" said, that you don't need to add an ampersand on code like this, because you get the same result without it.
function myClass() {
//...some code...
return $this;
}
$myObj =& new myClass()
I just experienced something else. I have a pretty complicated/large class relation ship in one part of our software. And when I didn't enter the ampersand I got a totally different result from my function, an array from a totaly different array.
So my suggestion is that you enter the ampersand so it looks like this.
function &getError()
{
return $this->systemError;
}
$errors = & $connection->getError();
agggka at hotmail dot com
18-Feb-2004 08:49
to jazfresh at hotmail dot com (comments from 17-Feb-2004)
You don't really need array_keys()
<?
function &findMyObjectByName($name)
{
foreach ($this->my_array as $key => $obj)
{
if (0 == strcmp($name, $obj->getName()))
{ return ($my_array[$key]); }
}
return (null); }
?>
jazfresh at hotmail dot com
17-Feb-2004 05:39
Say you want to search an array, with the intention of returning a reference to the value (so that the parent function can directly edit the array element). You cannot use "foreach" or "each" in the traditional way, because those functions will make a copies of the object, rather than return references to the original array element.
<?
function &findMyObjectByName($name) {
foreach($this->my_array as $obj) {
if($obj->getName() == $name) {
return $obj;
}
}
return null; }
?>
To avoid this pitfall, use array_keys():
<?
function &findMyObjectByName($name) {
foreach(array_keys($this->my_array) as $key) {
if($this->my_array[$key]->getName() == $name) {
return $my_array[$key];
}
}
return null; }
?>
php-doc-21-may-2003 at ryandesign dot com
21-May-2003 08:34
To Jeb in regard to his comment from March 2003, the easier way to handle your situation -- the possibility that the server will have an older version of PHP which doesn't support $_GET -- is to include the following at the top of every page:
if (!isset($_GET)) $_GET =& $GLOBALS['HTTP_GET_VARS'];
Then just use $_GET everywhere as usual.
joachim at lous dot org
10-Apr-2003 05:46
So to make a by-reference setter function, you need to specify reference semantics _both_ in the parameter list _and_ the assignment, like this:
class foo{
var $bar;
function setBar(&$newBar){
$this->bar =& newBar;
}
}
Forget any of the two '&'s, and $foo->bar will end up being a copy after the call to setBar.
todd at nemi dot net
11-Feb-2002 01:15
tbutzon@imawebdesigner.com Makes an excellent point in his reference examples, however, what you find in practice is that you do not need the & in the function definition to actually assign the reference. It is redundant.
The proper way to return a reference is by using:
function &myClass() {
//...some code...
return $this;
}
$myObj =& new myClass()
...however, this produces the exact same result:
function myClass() {
//...some code...
return $this;
}
$myObj =& new myClass()
Apparently, the Ampersand on the assignment is all that is really needed for a reference to truly be assigned. The Ampersand on the function definition actually does nothing.
pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu
01-May-2001 03:02
Just a note for others who may run into this. When the manual says that references are bound to the same copy of the content, it means exactly that.
So doing something like this,
$a = 1;
$b =& $a;
$b = 2;
print "$a $b";
will print '2 2'. This can be frustrating to track down if, like me, you are used to Perl where you explicitly dereference refrences. Since $a and $b both reference the same data, changing either, changes both.
It may be obvious to others, but if you are familiar with pointers or Perl references the automatic dereferencing can be confusing if you forget about it.
| |