Passagem por referência

Você pode passar uma variável por referência a uma função de forma que a função possa modificar a variável. A sintaxe é a seguinte:

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

$a=5;
foo($a);
// $a é 6 aqui
?>

Nota: Não há o sinal de referência na chamada da função - apenas nas definições de função. As definições de função, sozinhas, são suficientes para passar o argumento por referência. A partir do PHP 5.3.0 você receberá um alerta de "call-time pass-by-reference" está obsoleto quando usar o & na em chamadas de função: foo(&$a);. A partir do PHP 5.4.0, passagem por referência na chamada foi removido, e usar isso causará um erro fatal.

Os itens seguintes podem ser passados por referência:

  • Variáveis, como foo($a)
  • Instruções new, como foo(new foobar())
  • Referências retornadas de fumções, como:

    <?php
    function foo(&$var)
    {
        
    $var++;
    }
    function &
    bar()
    {
        
    $a 5;
        return 
    $a;
    }
    foo(bar());
    ?>
    Veja mais sobre isso em retorno por referência.

Nenhuma outra expressão pode ser passada por referência pois não tem comportamento definido. Os seguintes exemplos de passagem por referência são inválidos:

<?php
function foo(&$var)
{
    
$var++;
}
function 
bar() // Repare que falta &
{
    
$a 5;
    return 
$a;
}
foo(bar()); // Produz um erro fatal no 5.0.5, alerta de padrão estrito
            // no PHP 5.1.1, e alerta no PHP 7.0.0

foo($a 5); // Expressão, não variável
foo(5); // Produz erro fatal
?>
Esses requerimentos valem a partir do PHP 4.0.4.

add a note add a note

User Contributed Notes 9 notes

up
71
tnestved at yahoo dot com
1 year 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
10
mike at eastghost dot com
1 year ago
beware unset()  destroys references

$x = 'x';
change( $x );
echo $x; // outputs "x" not "q23"  ---- remove the unset() and output is "q23" not "x"

function change( & $x )
{
    unset( $x );
    $x = 'q23';
    return true;
}
up
10
fdelizy at unfreeze dot net
9 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
1
phpnet at holodyn dot com
2 years 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
4
diabolos @t gmail dot com
3 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
0
no at spam dot please
1 year ago
agreed : this change produces less readable code.

additionally, it breaks many existing perfectly working codes which are not portable anymore and in some cases will require complex modifications

another issue regards the fatal error that is produced : how the hell am i supposed to do if i want to allow the user to use a value that is not even in a variable, or the return or a function call, or use call_user_func... this produces many occasions for a code to even break at run time
up
0
Sergio Santana: ssantana at tlaloc dot imta dot mx
11 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
-3
obscvresovl at NOSPAM dot hotmail dot com
11 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.
up
-8
pillepop2003 at yahoo dot de
11 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!
To Top