引用的解释
在线手册:中文  英文

引用传递

可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值。语法如下:

<?php
function foo(&$var)
{
    
$var++;
}

$a=5;
foo($a);
// $a is 6 here
?>
注意在函数调用时没有引用符号——只有函数定义中有。光是函数定义就足够使参数通过引用来正确传递了。在最近版本的 PHP 中如果把 & 用在 foo(&$a); 中会得到一条警告说“Call-time pass-by-reference”已经过时了。

以下内容可以通过引用传递:

任何其它表达式都不能通过引用传递,结果未定义。例如下面引用传递的例子是无效的:

<?php
function bar() // Note the missing &
{
    
$a 5;
    return 
$a;
}
foo(bar()); // 自 PHP 5.0.5 起导致致命错误
foo($a 5// 表达式,不是变量
foo(5// 导致致命错误
?>
这些条件是 PHP 4.0.4 以及以后版本有的。


引用的解释
在线手册:中文  英文

用户评论:

Anonymous (2013-06-21 13:46:17)

assssssss sssssss vev
ewv
wev
we
v
wev
ewwwwwwwwwww

lubaev dot ka at gmail dot com (2013-06-15 10:09:12)

<?php
error_reporting
(E_ALL);

function 
f( &$arg ) {
    echo 
$arg;
}

// 1.
f( function(){return 1000;});
// Fatal error: Only variables can be passed by reference in ...
// 2.
f1000 );
// Fatal error: Only variables can be passed by reference in ...
// 3.
f$a 1000);
// Strict Standards: Only variables should be passed by reference in ...
// 1000

diabolos @t gmail dot com (2012-07-27 14:46:36)

<?php

/*

  This function internally swaps the contents between 
  two simple variables using 'passing by reference'.

  Some programming languages have such a swap function 
  built in, but PHP seems to lack such a function.  So, 
  one was created to fill the need.  It only handles 
  simple, single variables, not arrays, but it is
  still a very handy tool to have.

  No value is actually returned by this function, but 
  the contents of the indicated variables will be 
  exchanged (swapped) after the call.
*/

// ------------------------------------------
// Demo call of the swap(...) function below.

 
$a 123.456;
 
$b 'abcDEF';
  
 print 
"<pre>Define:\na = $a\nb = '$b'</pre>";
 
swap($a,$b);
 print 
"<pre>After swap(a,b):\na = '$a'\nb = $b</pre>";

// -------------------------------

   
function swap (&$arg1, &$arg2)
{

// Swap contents of indicated variables.
   
$w=$arg1;   $arg1=$arg2;   $arg2=$w;
}

?>

David R (2012-06-15 15:45:25)

One thing I reckon is simple but pretty cool is that if you take a reference from a reference, they both point to the same thing original variable (as you would hopefully expect).

This means you can pass in a variable (by reference), and then make a reference from that, you can make changes to the original variable later.

<?php
class DelayedChange {
    private 
$changeTarget;
    public function 
prepareForChange(&$target) {
        
// Save a reference to the variable we want to change
        
$this->changeTarget = &$target;
    }
    public function 
change($value) {
        
// Assign a new value
        
$this->changeTarget $value;
    }
}

$testVar "value 1";

$delayedChange = new DelayedChange();
$delayedChange->prepareForChange($testVar);
echo (
$testVar."<br>\n");  // outputs "value 1"
$delayedChange->change("value 2");
echo (
$testVar."<br>\n");  // outputs "value 2"
?>

(naturally, this only works if you make $changeTarget a reference - if you just write "$this->changeTarget = $target" then it copies $testVar's value instead of taking a new reference to it.)

sagiwagi at live dot com (2012-05-22 08:20:11)

It should be noted that documentation above does not fully show 
how extract a value from the following code: 

<?php
function foo(&$var)
{
    
$var++;
}
function &
bar()
{
    
$a 5;
    return 
$a;
}
foo(bar());
?>

The following will work: 

<?php
function foo(&$var)
{
    
$var++;
return 
$var
}
function &
bar()
{
    
$a 5;
    return 
$a;
}
echo 
foo(bar());
?>

jocelyn dot heuze at gmail dot com (2011-10-18 22:12:01)

Please note that you can't pass NULL to a function by reference, unless it's as a default value.

<?php

function foo(&$a NULL) {
    if (
$a === NULL) {
        echo 
"NULL\n";
    } else {
        echo 
"$a\n";
    }
}

foo(); // "NULL"
foo(5); // "5"
foo(NULL); // Produces an error

?>

4d88 dot results at gmail dot com (2011-05-03 20:15:07)

This is the way how we use pointer to access variable inside the class.

<?php
class talker{

    private 
$data 'Hi';

    public function & 
get(){
        return 
$this->data;
    }
    
    public function 
out(){
        echo 
$this->data;
    }    

}

$aa = new talker();
$d = &$aa->get();

$aa->out();
$d 'How';
$aa->out();
$d 'Are';
$aa->out();
$d 'You';
$aa->out();
?>

the output is "HiHowAreYou"

northhero at gmail dot com (2010-08-24 00:25:17)

Someone mentioned that passing reference doesn't work as  expected from within call_user_func(). For example:

<?php
$string 
'string'
function 
change(&$str) {
    
$str 'str';
}
call_user_func('change'$string);
echo 
$string;
?>

output:
string               //not as expected 'str'

Here we could assume call_user_func as below

<?php
function call_user_funct($func$param) {
    
$func($param);
}
?>

As calling $func() inside call_user_funct, here is change(), the variable $param is copied to a third variable then the temp variable is passed to the $func. So $str only hold the reference of the temp variable inside change().
Of course , if we pass  &$string directly to call_user_func we could always get the result as expected (str).

northhero at gmail dot com (2010-08-23 19:02:11)

Passing variable reference to function instead of declaring the function parameter type to reference also could get the result as expected. 

<?php
$string 
'string';
function 
change($str) {
    
$str 'str';
}
change(&$string);
echo 
$string;
?>

yeild

str

PhoneixSegovia at GOOGLEMAILSERVER dot com (2010-07-06 08:05:45)

If you call it without nothing (no variable, no constant) then a new variable is created with null or the default parameter.
If a null parameter is passed, then this (null) variable is used, even with a default value specified.

A simple example:
<?php

print '<pre>';

function 
foo(&$a=5){
    
$a +=2;
    print 
"\nIn foo => $a";
}

function 
bar(&$a){
    
$a += 2;
    print 
"\nIn bar => $a";
}

$a;
$b;
print 
"Initial:\n";
var_dump($a$b);

foo();
bar();

print 
"\nAfter void call:\n";
var_dump($a$b);

foo($a);
bar($b);

print 
"\nAfter passed:\n";
var_dump($a$b);

print 
'</pre>';
?>

Output is:
"Initial:
NULL
NULL

In foo => 7
In bar => 2
After void call:
NULL
NULL

In foo => 2
In bar => 2
After passed:
int(2)
int(2)"

Note that null is equal to 0 in a mathematical expresion.

rvw at cosninix dot com (2010-02-08 14:13:56)

Watch out that passing an uninitialised variable to a function will create the variable and will NOT give a NOTICE-undefined variable:

<?php
function ifnull(&$v,$default) { 
   if (isset(
$v)) return $v;
   return 
$default;
}

$p=array();
$p['apple']=3;
echo 
ifnull($p['apple'],4);   -> 3
echo ifnull($p['pear'],5);    -> 5  No "undefined index" here
if (isset(
$p['pear'])) echo "pear is set"; else echo "pear not set"; -> not set
if (array_key_exists('pear',$p)) echo "pear exists"; else echo "pear doesn't exist";  -> pear exists!
?>

Tom (2009-07-20 16:54:06)

Still puzzled with references?

See this code:
<?php
function a(&$a, &$b) { $a =& $b; }
$a 1;
$b 2;
a($a$b);
$b 3;
print 
$a;
?>

If you expect the output to be 3, you are wrong. $a remains unchanged and the output is 1. The reference was NOT assigned to $a.

Now let's try this one:
<?php
function a(&$a, &$b) { $a $b; }
$a 1;
$b 2;
a($a$b);
$b 3;
print 
$a;
?>

If you thought that now the output would be 3, you are wrong again. It's 2.

However this:
<?php
$a 
1;
$b 2;
$a =& $b;
$b 3;
print 
$a;
?>
Actually outputs 3.

But how about Objects? Objects, you might think, are always passed by reference. So this should work!

Well, let's check it out:
<?php
function a($a$b) { $a $b; }
$a = new StdClass;
$a->1;
$b = new StdClass;
$b->2;
a($a$b);
$b->3;
print 
$a->i;
?>
Outputs 1! So obviously you are wrong again.

What's the reason? Simple! The first (and the last) code example above translates to this fragment:
<?php
$a 
1;
$b 2;
$a1 =& $a;
$b1 =& $b;
$a1 =& $b1;
$b 3;
print 
$a;
?>

Now THAT makes it clear, right?

If you are referencing a reference you are NOT making the original pointer change it's destination like in Java or C#, because it is not dereferenced automatically. Instead you are overwriting the local pointer. You will make $a1 point to $b, which has no influence on the original $a.

This is different from all you might expect if you have been programming in other OO-languages before, so you should keep that in mind.

me at khurram dot nl (2008-09-12 07:55:42)

in php 5.2.0 for classes

$obj1  =  $obj2;
is equal to
$obj1  =  &$obj2;"

<?php

class {
    public 
$var '';
    }
  
$a = new z();
$b   =&  $a;
$c  $a;

$a->var null;

var_dump($a);
print 
'<br>';
var_dump($b);
print 
'<br>';
var_dump($c);
print 
'<br><br>';

$a->var 2;

var_dump($a);
print 
'<br>';
var_dump($b);
print 
'<br>';
var_dump($c);
print 
'<br><br>';

?>

mehea (2008-05-19 17:04:04)

New in PHP5:  assign default value to
pass-by-reference paramter.

I didn't believe it even when I read
http://devzone.zend.com/article/1714-Whats-New-in-PHP-5

Then I tried this:

<?php
function my_func(&$arg 22) {
    if (
$arg == 22) {
        print 
'$arg is '$arg;
    }
}
my_func();
?>

Guess what? It works, even tho' not clear about what $arg is actually referencing!

Chuckie (2007-10-28 08:33:35)

If you intend to pass a copy of an object to a function, then you should use 'clone' to create a copy explicity.  In PHP5, objects appear to always be passed by reference (unlike PHP4), but this is not strictly true.

The way I think of it is that if you use '=&' (or you explicitly pass to a function by reference) the variable behaves like a C++ reference, except that you can re-assign the reference to something else (which is not possible in C++).

When you use '=' with an object, it is more like you are dealing with a pointer (if you think in this way, the '->' access element through pointer operator has the same behaviour in C++).

<?php

class {
    public 
$var '';
    }
   
function 
f(&$obj1$obj2$obj3$obj4) {
  
$obj1->var null;
  
$obj2->var null;
  
$obj3 = new z();
  
$obj3->var null;
  
$obj4 = clone $obj4;
  
$obj4->var null;
  }
$a = new z();
$b = new z();
$c = new z();
$d = new z();
f($a$b$c$d);

var_dump($a); // object(z)#1 (1) { ["var"] => NULL }
var_dump($b); // object(z)#2 (1) { ["var"] => NULL }
var_dump($c); // object(z)#3 (1) { ["var"] => string(0) "" }
var_dump($d); // object(z)#4 (1) { ["var"] => string(0) "" }

?>

Stephen
08-Jul-2007 04:54
jcastromail at yahoo dot es stated:
****
in php 5.2.0 for classes

$obj1  =  $obj2;
is equal to
$obj1  =  &$obj2;"
****

However, that is not completely true. While both = and =& will make a variable refer to the same object as the variable being assigned to it, the explicit reference assignment (=&) will keep the two variables joined to each other, whereas the assignment reference (=) will make the assigned variable an independent pointer to the object. An example should make this clearer:

<?php

class {
    public 
$var '';
    }
   
$a = new z();
$b   =&  $a;
$c  $a;

$a->var null;

var_dump($a);
print 
'<br>';
var_dump($b);
print 
'<br>';
var_dump($c);
print 
'<br><br>';

$a 2;

var_dump($a);
print 
'<br>';
var_dump($b);
print 
'<br>';
var_dump($c);
print 
'<br><br>';

?>

This outputs:

object(z)#1 (1) { ["var"]=> NULL }
object(z)#1 (1) { ["var"]=> NULL }
object(z)#1 (1) { ["var"]=> NULL }

int(2)
int(2)
object(z)#1 (1) { ["var"]=> NULL }

So although all 3 variables reflect changes in the object, if you reassign one of the variables that were previously joined by reference to a different value, BOTH of those variables will adopt the new value.

Perhaps this is because =& statements join the 2 variable names in the symbol table, whereas = statements applied to objects simply create a new independent entry in the symbol table that simply points to the same location as other entries. I don't know for sure - I don't think this behavior is documented in the PHP manual, so perhaps somebody with more knowledge of PHP's internals can clarify what is going on.

sony-santos at bol dot com dot br (2007-07-27 13:06:18)

Just another workaround for default values to parameters by ref in response to mogmios, bobbykjack, andrzej, fdelizy, petruzanautico, Train Boy, and php community.

<?php
# php 4.3.10

# note there's no & in function declaration:
function f($a = array('default value')) {
  
$a[0] .= " processed<br/>";
  echo 
$a[0];
}

f(); # default value processed

$b 'foo';

f(array(&$b)); # foo processed (note the & here)

echo $b# foo processed
?>

doron (2007-07-09 06:06:08)

I found that
f1(&$par=0);
behaves differently in 5.2.4 thatn in 5.0.4
in 5.2.4 the par is assined to zero AFTER function call
and thus, par is allways ZERO !
in 5.0.4 in is INITIALIZED to zero, BEFORE function call!

petruzanautico at yahoo dot com dot ar (2006-09-25 13:30:25)

Actually there is a way to give a default value to a reference argument, if you need it badly.
It fires a warning, but you can prefix the function call with an @.
Of course, you cannot pass literals by reference.

<?php
function byref( &$ref )
{
  if( !isset( 
$ref ) )
    
$ref "default value";
  print 
$ref// default or given value? who knows!
}

$hi "some value ";
byref$hi ); // works fine
@byref(); // missing argument warning, but works
byref"hey!" ); // this will raise a fatal error
?>

fdelizy at unfreeze dot net (2006-08-12 09:32:43)

Some have noticed that reference parameters can not be assigned a default value. It's actually wrong, they can be assigned a value as the other variables, but can't have a "default reference value", for instance this code won't compile :

<?php
function use_reference$someParam, &$param =& $POST )
{
 ...

?>

But this one will work :

<?php
function use_reference$someParam, &$param null )
?>

So here is a workaround to have a default value for reference parameters :

<?php
$array1 
= array ( 'test''test2' );

function 
AddTo$key$val, &$array null)
{
    if ( 
$array == null )
    {
      
$array =& $_POST;
    }

    
$array$key ] = $val ;
}

AddTo"indirect test""test"$array1 );
AddTo"indirect POST test""test" );

echo 
"Array 1 " ;
print_r $array1);

echo 
"_POST ";
print_r$_POST );

?>

And this scripts output is :

Array 1 Array
(
    [0] => test
    [1] => test2
    [indirect test] => test
)
_POST Array
(
    [indirect POST test] => test
)

Of course that means you can only assign default reference to globals or super globals variables. 

Have fun

rmarscher (2005-09-15 15:42:10)

Not sure if this is obvious to everyone, but if you pass an object by reference into a function and then set that variable to the reference of a new object, the initial variable outside the function is still pointing to the original object.  

It became obvious to me why this is the case when I made a little diagram of what's actually happening in the system's memory, but before that when I was just looking at the code, it took me a while of testing before I realized what was going on.

Here's an example (I haven't tried in PHP5, but I would guess it works the same):
<?php
class Foo {}
class 
Bar {}

function & 
createBar()
{
  return new 
Bar;
}

function 
setBar(& $obj)
{
  echo 
get_class($obj) . "\n";
  
$obj = & createBar();
  echo 
get_class($obj) . "\n";
}

$test = new Foo;
setBar($test);
echo 
get_class($test);
?>

Outputs:
foo
bar
foo

pillepop2003 at yahoo dot de (2005-02-13 08:08:44)

PHP has a strange behavior when passing a part of an array by reference, that does not yet exist.

<?php
    
function func(&$a)
    {
        
// void();
    
}
    
    
$a['one'] =1;
    
func($a['two']);
?>    

var_dump($a) returns

    array(2) {
        ["one"]=>
        int(1)
        ["two"]=>
        NULL
    }

...which seems to be not intentional!

obscvresovl at NOSPAM dot hotmail dot com (2004-12-25 22:51:10)

Just a simple note...

<?php

$num 
1;

function 
blah(&$var)
{
    
$var++;
}

blah($num);

echo 
$num#2

?>

<?php

$num 
1;

function 
blah()
{
    
$var =& $GLOBALS["num"];
    
$var++;
}

blah();

echo 
$num#2

?>

Both codes do the same thing! The second code "explains" how passage of parameters by reference works.

jbr at diasparsoftware dot com (2004-09-28 09:46:30)

Strangely enough, I had to put "&" on the call site, but not on the function parameter list, in order to get this to work. Here is the code:

<?php
class TestRunner {
    var 
$passed;
    var 
$failed;
    var 
$tests;
    
    function 
TestRunner() {
        
$this->passed 0;
        
$this->failed 0;
        
$this->tests = array();
    }

    function 
addTest($test) {
        
$this->tests[] = $test;
    }

    function 
signalFailed() {
        
$this->failed++;
    }
        
    function 
runTests() {
        foreach (
$this->tests as $i => $eachName) {
            
call_user_func($eachName, &$this);
        }
    }
        
    function 
report() {
        
?>
        <p><?= count($this->tests?> run, <?= $this->passed ?> passed, <?= $this->failed ?> failed</p>        
        <?php
    
}
}

function 
testNullStringIsEmpty($testRunner) {
    
$testRunner->signalFailed();
}

$testRunner = new TestRunner;
$testRunner->addTest("testNullStringIsEmpty");
$testRunner->runTests();
$testRunner->report();
?>

Notice that testNullStringIsEmpty() does not declare that it wants a reference to a test runner, whereas on the function call site, we pass in &$this. When I run this, I get "1 run, 0 passed, 1 failed"; but when I switch the location of the & to the function parameter list, I get "1 run, 0 passed, 0 failed". This is the exact opposite to what the manual claims. I have no idea why that is.

Sergio Santana: ssantana at tlaloc dot imta dot mx (2004-09-10 08:25:16)

Sometimes we need functions for building or modifying arrays whose elements are to be references to other variables (arrays or objects for instance). In this example, I wrote two functions 'tst' and 'tst1' that perform this task. Note how the functions are written, and how they are used.

<?php
function tst(&$arr$r) {
  
// The argument '$arr' is declared to be passed by reference, 
  // but '$r' is not;
  // however, in the function's body, we use a reference to 
  // the '$r' argument
  
  
array_push($arr, &$r); 
  
// Alternatively, this also could be $arr[] = &$r (in this case)
}
  
$arr0 = array();          // an empty array
$arr1 = array(1,2,3);   // the array to be referenced in $arr0

// Note how we call the function:
tst($arr0, &$arr1); // We are passing a reference to '$arr1' in the call !

print_r($arr0); // Contains just the reference to $arr1

array_push($arr05); // we add another element to $arr0
array_push($arr118); // we add another element to $arr1 as well

print_r($arr1);  
print_r($arr0); // Changes in $arr1 are reflected in $arr0

// -----------------------------------------
// A simpler way to do this:

function tst1(&$arr, &$r) {
  
// Both arguments '$arr' and '$r" are declared to be passed by
  // reference, 
  // again, in the function's body, we use a reference to 
  // the '$r' argument
  
  
array_push($arr, &$r); 
  
// Alternatively, this also could be $arr[] = &$r (in this case)
}

  
$arr0 = array();          // an empty array
$arr1 = array(1,2,3);   // the array to be referenced in $arr0

// Note how we call the function:
tst1($arr0$arr1); // 'tst1' understands '$r' is a reference to '$arr1'

echo "-------- 2nd. alternative ------------ <br>\n";

print_r($arr0); // Contains just the reference to $arr1

array_push($arr05); // we add another element to $arr0
array_push($arr118);

print_r($arr1);  
print_r($arr0); // Changes in $arr1 are reflected in $arr0

// This outputs:
// X-Powered-By: PHP/4.1.2
// Content-type: text/html
// 
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//         )
// 
// )
// Array
// (
//     [0] => 1
//     [1] => 2
//     [2] => 3
//     [3] => 18
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//             [3] => 18
//         )
// 
//     [1] => 5
// )
// -------- 2nd. alternative ------------ 
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//         )
// 
// )
// Array
// (
//     [0] => 1
//     [1] => 2
//     [2] => 3
//     [3] => 18
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//             [3] => 18
//         )
// 
//     [1] => 5
// )
?>

In both cases we get the same result.

I hope this is somehow useful

Sergio.

ben at mekhaye dot net (2004-09-01 14:27:39)

Passing arrays by reference doesn't work as I expected from within call_user_func. 

I had:

  <?php
  $arr 
= Array();
  
call_user_func(Array("ClassName","functionName"), $param1$param2$arr);
  
print_r($arr);

  class 
ClassName {

      
functionName($param1$param2, &$arr) {
        
$arr[0] = "apple";
        
$arr[1] = "banana";
        
print_r($arr);
      } 
  }
  
?>

I expected the output to be like:

  Array ( [0] => "apple" [1] => "banana" )
  Array ( [0] => "apple" [1] => "banana" )

but instead it was only:

  Array ( [0] => "apple" [1] => "banana" )

However, when I changed the function call to plain old:

  <?php
  $arr 
= Array();
  
ClassName::functionName($param1,$param2,$arr);
  
print_r($arr);
  
?>

Output was the expected:

  Array ( [0] => "apple" [1] => "banana" )
  Array ( [0] => "apple" [1] => "banana" )

php at meKILLTHIStatoandthisols dot org (2004-06-09 12:33:23)

Ever been in a situation where you have to write:

  <?php
    $t 
;
    
$x =& $t ;
  
?>

or

  <?php
    $t 
;
    
f$t ) ;
  
?>

because you cannot pass constants by value. The function

  <?php
    
function& pclone$v ) {
      return( 
$v ) ;
    }
  
?>

lets you get ridd of the temporary variable. You can write:

  <?php
    $x 
=& pclone) ;
  
?>

or

  <?php
    f
pclone) ) ;
  
?>

Alternatively you can use the other alternative ;-)

blistwon-php at designfridge dot com (2004-01-17 18:33:28)

One thing to note about passing by reference. If you plan on assigning the reference to a new variable in your function, you must use the reference operator in the function declaration as well as in the assignment. (The same holds true for classes.)

<?php
function f1(&$num) {
    
$num++;
}
function 
f2(&$num) {
    
$num1 $num;
    
$num1++;
}
function 
f3(&$num) {
    
$num1 = &$num;
    
$num1++;
}

$myNum 0;
print(
"Declare myNum: " $myNum "<br />\n");
f1($myNum);
print(
"Pass myNum as ref 1: " $myNum "<br />\n");
f2($myNum);
print(
"Pass myNum as ref 2: " $myNum "<br />\n");
f3($myNum);
print(
"Pass myNum as ref 3: " $myNum "<br />\n");
?>

-------------------------------------------------------
OUTPUT
-------------------------------------------------------
 Declare myNum: 0
 Pass myNum as ref 1: 1
 Pass myNum as ref 2: 1
 Pass myNum as ref 3: 2
-------------------------------------------------------

Hope this helps people trying to detangle any problems with pass-by-ref.

易百教程