可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值。语法如下:
<?php
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
// $a is 6 here
?>
以下内容可以通过引用传递:
从函数中返回的引用,例如:
<?php
function &bar()
{
$a = 5;
return $a;
}
foo(bar());
?>
任何其它表达式都不能通过引用传递,结果未定义。例如下面引用传递的例子是无效的:
<?php
function bar() // Note the missing &
{
$a = 5;
return $a;
}
foo(bar()); // 自 PHP 5.0.5 起导致致命错误
foo($a = 5) // 表达式,不是变量
foo(5) // 导致致命错误
?>
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.
f( 1000 );
// 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->i = 1;
$b = new StdClass;
$b->i = 2;
a($a, $b);
$b->i = 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 z {
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 z {
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 z {
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($arr0, 5); // we add another element to $arr0
array_push($arr1, 18); // 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($arr0, 5); // we add another element to $arr0
array_push($arr1, 18);
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 = 1 ;
$x =& $t ;
?>
or
<?php
$t = 1 ;
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( 1 ) ;
?>
or
<?php
f( pclone( 1 ) ) ;
?>
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.