SunshinePHP Developer Conference 2015

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:

  • Variablen, zum Beispiel foo($a)
  • "New"-Ausdrücke, zum Beispiel foo(new foobar())
  • Referenzen, zurückgegeben von einer Funktion, zum Beispiel:

    <?php
    function &bar()
    {
        
    $a 5;
        return 
    $a;
    }
    foo(bar());
    ?>
    Es gibt detailliertere Erläuterungen zur Rückgabe by-reference.

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.

add a note add a note

User Contributed Notes 7 notes

up
4
diabolos @t gmail dot com
2 years ago
<?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;
}

?>
up
3
fdelizy at unfreeze dot net
8 years ago
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
up
2
pillepop2003 at yahoo dot de
9 years ago
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!
up
1
phpnet at holodyn dot com
6 months ago
The notes indicate that a function variable reference will receive a deprecated warning in the 5.3 series, however when calling the function via call_user_func the operation aborts without fatal error.

This is not a "bug" since it is not likely worth resolving, however should be noted in this documentation.
up
1
Sergio Santana: ssantana at tlaloc dot imta dot mx
10 years ago
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.
up
1
tnestved at yahoo dot com
9 days ago
By removing the ability to include the reference sign on function calls where pass-by-reference is incurred (I.e., function definition uses &), the readability of the code suffers, as one has to look at the function definition to know if the variable being passed is by-ref or not (I.e., potential to be modified).  If both function calls and function definitions require the reference sign (I.e., &), readability is improved, and it also lessens the potential of an inadvertent error in the code itself.  Going full on fatal error in 5.4.0 now forces everyone to have less readable code.  That is, does a function merely use the variable, or potentially modify it...now we have to find the function definition and physically look at it to know, whereas before we would know the intent immediately.
up
0
obscvresovl at NOSPAM dot hotmail dot com
9 years ago
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.
To Top