PHP Doku:: Parameterübergabe per Referenz - language.references.pass.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchSprachreferenzReferenzen in PHPParameterübergabe per Referenz

Ein Service von Reinhard Neidl - Webprogrammierung.

Referenzen in PHP

<<Was Referenzen nicht sind

Referenzen zurückgeben>>

Parameterübergabe per Referenz

Man kann Variablen an Funktionen per Referenz übergeben, so dass die Funktion ihre Argumente modifizieren kann. Dazu benutzt man folgende Syntax:

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

$a=5;
foo($a);
// $a ist 6
?>
Zu beachten ist, dass kein Referenz-Zeichen beim Funktionsaufruf steht, nur in der Funktionsdefinition. Diese allein ist ausreichend, um das Argument per Referenz zu übergeben. In neueren PHP-Versionen gibt es eine Warnung, dass die Benutzung von "Call-time pass-by-reference" mit Hilfe von & in foo(&$a); veraltet ist.

Folgende Dinge können per Referenz übergeben werden:

Alle anderen Ausdrücke sollte nicht per Referenz übergeben werden, da das Ergebnis undefiniert ist. Folgende Beispiele sind etwa ungültig:

<?php
function bar() // Beachte das fehlende &
{
    
$a 5;
    return 
$a;
}
foo(bar()); // Fatal error seit PHP 5.0.5

foo($a 5); // Ausdruck, keine Variable
foo(5); // Fatal error
?>
Diese Anforderungen gelten für PHP 4.0.4 und später.


20 BenutzerBeiträge:
- Beiträge aktualisieren...
northhero at gmail dot com
24.08.2010 9:25
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
24.08.2010 4:02
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
6.07.2010 17:05
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
8.02.2010 23:13
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
21.07.2009 1:54
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
12.09.2008 16:55
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
20.05.2008 2: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
28.10.2007 17:33
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
27.07.2007 22:06
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
9.07.2007 15:06
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
25.09.2006 22:30
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
12.08.2006 18:32
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
16.09.2005 0:42
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
13.02.2005 17:08
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
26.12.2004 7:51
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
28.09.2004 18:46
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
10.09.2004 17:25
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
1.09.2004 23:27
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
9.06.2004 21:33
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
18.01.2004 3:33
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.



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)