309

Are PHP variables passed by value or by reference?

hichris123
  • 10,145
  • 15
  • 56
  • 70
cmcculloh
  • 47,596
  • 40
  • 105
  • 130
  • 6
    Also see [are-arrays-in-php-passed-by-value-or-by-reference](http://stackoverflow.com/questions/2030906/are-arrays-in-php-passed-by-value-or-by-reference) – nawfal Nov 18 '15 at 13:56
  • 2
    good explaination in http://codeexpertz.com/blog/php/pass-value-and-pass-reference-php-example – Premlatha Apr 02 '19 at 08:38

16 Answers16

375

It's by value according to the PHP Documentation.

By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.

To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}

$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>
Prabu Guna
  • 344
  • 1
  • 3
  • 14
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • 5
    I also had this doubt ( newbie ) - so just to be clear , this would be the same as `$str = add_some_extra($str);` if I was not using the reference , right ? then what is the real added value of that ? – Obmerk Kronen Nov 24 '13 at 06:06
  • 9
    @Obmerk If you were _not_ using the ampersand to signify by reference, it would not be equivalent. Notice how the function has no return statement, so `$str` would be assigned null, in your case. – The Unknown Dev Jan 22 '15 at 19:31
  • if you do it this way @ObmerkKronen then you'll have to return the value and catch it through your code too. The initial variable will remain the same otherwise. – Nabeel Khan Apr 04 '16 at 20:54
  • 2
    I'm wondering if pass by reference has some performance benefits or not? I'm passing a large array & by default it is pass by value. So, if I use call by reference then, will there be some performance wise benefit??? (keeping the array values unchanged during the whole process) – Choxx Oct 08 '16 at 05:31
  • 5
    the real benefit is that you can manipulate/return muliple values. You are also able to pass variables by reference and still let the function return something. – Martin Schneider Jun 18 '17 at 13:21
  • 3
    @Choxx There isn't any need to pass an array by reference for performance. The PHP engine uses copy-on-write - it doesn't physically copy the array *unless* it is modified in one of the scopes where it is visible. Then it makes a copy so the modification only applies in one place. – bdsl Dec 04 '20 at 12:20
  • If I get reference like `$byRef = & $myHugeMap['my-key'];`, how can I cast `$byRef` to a by-value variable, without fetching again from `$myHugeMap`??? In C/C++ we could do`: int $byValueInt = $byRefInt;` Or`: int $byValueInt = * $byPointerInt;` – Top-Master May 09 '23 at 03:47
97

In PHP, by default, objects are passed as reference to a new object.

See this example:

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
   $obj->abc = 30;
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30

Now see this:

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.

Now see this:

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue(&$obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.

I hope you can understand this.

Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
hardik
  • 9,141
  • 7
  • 32
  • 48
  • 4
    1st ex, the value of the reference of the obj is passed to the function, changes to the obj using the new reference will reflect to all other references pointing to the same obj. 2nd ex, again the VALUE of the reference of the obj is passed to the function, the function is changing the value of the reference to point to a new obj, the old obj stays the same. 3rd ex, the reference of the value of the reference of the obj is passed into the function, thus the changes in the function is operating on the same obj. – s-hunter Apr 28 '15 at 02:26
  • 1
    This example is unnecessarily complicated. `$y` isn't needed - there is nothing in `function changeValue` that requires it to be inside `class Y`, so that tangles together two unrelated concepts. I would move `function changeValue` to the outer scope, just above `$x = new X();`. Remove all references to `$y`. Now its easier to see that the first two examples leave $x alone, and the third one changes its contents to `new Y()`. Which would be easier to see if you dumped the `type` of `$x` - the fact that both `X` and `Y` happen to include a `$abc` field is also irrelevant to what is demonstrated – ToolmakerSteve Jul 01 '19 at 23:22
  • I hate the behavior in first example. – André Walker Mar 09 '23 at 12:43
62

It seems a lot of people get confused by the way objects are passed to functions and what passing by reference means. Object are still passed by value, it's just the value that is passed in PHP5 is a reference handle. As proof:

<?php
class Holder {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return $this->value;
    }
}

function swap($x, $y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Outputs:

a, b

To pass by reference means we can modify the variables that are seen by the caller, which clearly the code above does not do. We need to change the swap function to:

<?php
function swap(&$x, &$y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Outputs:

b, a

in order to pass by reference.

Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
grom
  • 15,842
  • 19
  • 64
  • 67
  • 20
    I think this proof is a misinterpretation. It looks like you were trying to swap references. You have a problem with how objects are assigned. You are reassigning the reference which is immutable. It's the value it points to that can be changed from inside. The redefinition of swap is now passing **x, which allows you to change *x. The problem is in thinking that $x = $y would change what $x originally points to. – grantwparks Jun 17 '12 at 20:26
  • 11
    *This isn't a proof*. The output of the first example is exactly what you'd expect if the current value of the entire object was passed to the `swap` function; in other words, if objects were "passed by value". On the other hand, it's also exactly what you'd expect if an object handle was passed to the function, which is actually what happens. Your code doesn't distinguish between these two cases. – EML May 12 '15 at 21:58
  • `Object are still passed by value, it's just the value that is passed in PHP5 is a reference handle` no. That's like saying passing a pointer to a C function is pass by value. It's not. It's a reference. Yes, a reference is a type of value, but it's still a reference. `To pass by reference means we can modify the variables that are seen by the caller` indeed, which you can do with an object: `$object->foo = 1;` will be seen by the caller. In your example you are assigning a *new reference* to the name, which erases the old reference. That does not make it less of a reference. – DimeCadmium Mar 22 '22 at 22:21
  • What the PHP docs misleadingly refer to as a "reference" `&$foo` would be more appropriately called an alias or a binding. "Pass by value" and "pass by reference" (and indeed "reference") have existing meanings outside the scope of PHP, with which PHP's bizarre definition is not even remotely compatible. – DimeCadmium Mar 22 '22 at 22:26
37

http://www.php.net/manual/en/migration5.oop.php

In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).

Karl Seguin
  • 21,574
  • 5
  • 44
  • 49
33

PHP variables are assigned by value, passed to functions by value and when containing/representing objects are passed by reference. You can force variables to pass by reference using an '&'.

Assigned by value/reference example:

$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";

print ("var1: $var1, var2: $var2, var3: $var3);

output:

var1: test, var2: final test, var3: final test

Passed by value/reference example:

$var1 = "foo";
$var2 = "bar";

changeThem($var1, $var2);

print "var1: $var1, var2: $var2";

function changeThem($var1, &$var2){
    $var1 = "FOO";
    $var2 = "BAR";
}

output:

var1: foo, var2 BAR

Object variables passed by reference example:

class Foo{
    public $var1;

    function __construct(){
        $this->var1 = "foo";
    }

    public function printFoo(){
        print $this->var1;
    }
}


$foo = new Foo();

changeFoo($foo);

$foo->printFoo();

function changeFoo($foo){
    $foo->var1 = "FOO";
}

output:

FOO

(The last example could be better probably.)

Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
cmcculloh
  • 47,596
  • 40
  • 105
  • 130
  • 3
    "Objects" are not values in PHP5 and cannot be "passed". The value of `$foo` is a *pointer to an object*. `$foo` is **passed by value** to the function `changeFoo()`, as `changeFoo()` did not declare its parameter with a `&`. – newacct Oct 01 '13 at 00:03
  • @newacct I think what you mean is that the pointer is passed by value but also the object is changed! – Achraf JEDAY Oct 16 '20 at 13:18
10

You can pass a variable to a function by reference. This function will be able to modify the original variable.

You can define the passage by reference in the function definition:

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

$result=5;
changeValue($result);

echo $result; // $result is 6 here
?>
Mahsin
  • 638
  • 4
  • 18
8

TL;DR: PHP supports both pass by value and pass by reference. References are declared using an ampersand (&); this is very similar to how C++ does it. When the formal parameter of a function is not declared with an ampersand (i.e., it's not a reference), everything is passed by value, including objects. There is no distinction between how objects and primitives are passed around. The key is to understand what gets passed along when you pass in objects to a function. This is where understanding pointers is invaluable.

For anyone who comes across this in the future, I want to share this gem from the PHP docs, posted by an anonymous user:

There seems to be some confusion here. The distinction between pointers and references is not particularly helpful. The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)

First principle: A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)

2nd principle, and source of the most confusion: Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.

3rd principle: "&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.

Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.

And here's the example they provide:

<?php

//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.

$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.

//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"

function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}

function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}

?>

I wrote an extensive, detailed blog post on this subject for JavaScript, but I believe it applies equally well to PHP, C++, and any other language where people seem to be confused about pass by value vs. pass by reference.

Clearly, PHP, like C++, is a language that does support pass by reference. By default, objects are passed by value. When working with variables that store objects, it helps to see those variables as pointers (because that is fundamentally what they are, at the assembly level). If you pass a pointer by value, you can still "trace" the pointer and modify the properties of the object being pointed to. What you cannot do is have it point to a different object. Only if you explicitly declare a parameter as being passed by reference will you be able to do that.

6

You can do it either way.

Put an '&' symbol in front and the variable you are passing becomes one and the same as its origin i.e. you can pass by reference, rather than make a copy of it.

so

    $fred = 5;
    $larry = & $fred;
    $larry = 8;
    echo $fred;//this will output 8, as larry and fred are now the same reference.
Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
Bingy
  • 643
  • 4
  • 9
5

Variables containing primitive types are passed by value in PHP5. Variables containing objects are passed by reference. There's quite an interesting article from Linux Journal from 2006 which mentions this and other OO differences between 4 and 5.

http://www.linuxjournal.com/article/9170

Polsonby
  • 22,825
  • 19
  • 59
  • 74
1

Objects are passed by reference in PHP 5 and by value in PHP 4. Variables are passed by value by default!

Read here: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html

Miha
  • 27
  • 1
  • 1
    "Objects" are not values in PHP5 and cannot be "passed". All variables are passed by value if the parameter of the function passed to does not have `&`. – newacct Oct 01 '13 at 00:04
  • @newacct not quite? Objects are [somewhat passed by reference](http://php.net/manual/en/language.oop5.references.php). I think I've observed that php objects can be modified by functions even when not defined with `&` in front of the parameters in the definition - if they were passed by value the object contained in the scope which called the function with it as a parameter would not be affected. – Félix Adriyel Gagnon-Grenier Dec 21 '14 at 10:24
  • 3
    @FélixGagnon-Grenier: Again, "objects" are not values and cannot be "passed". You cannot have a "variable" in PHP5 whose value is an "object", you can only have a value that is an object reference (i.e. a pointer to an object). Of course you can pass or assign a pointer to an object by value and modify the object it points to by calling a method that does such modifying. That has nothing to do with pass by reference. What type a value is and whether a parameter is pass-by-value/pass-by-reference are independent and orthogonal things. – newacct Dec 21 '14 at 10:28
1
class Holder
{
    private $value;

    public function __construct( $value )
    {
        $this->value = $value;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function setValue( $value )
    {
        return $this->value = $value;
    }
}

class Swap
{       
    public function SwapObjects( Holder $x, Holder $y )
    {
        $tmp = $x;

        $x = $y;

        $y = $tmp;
    }

    public function SwapValues( Holder $x, Holder $y )
    {
        $tmp = $x->getValue();

        $x->setValue($y->getValue());

        $y->setValue($tmp);
    }
}


$a1 = new Holder('a');

$b1 = new Holder('b');



$a2 = new Holder('a');

$b2 = new Holder('b');


Swap::SwapValues($a1, $b1);

Swap::SwapObjects($a2, $b2);



echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";

echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";

Attributes are still modifiable when not passed by reference so beware.

Output:

SwapObjects: b, a SwapValues: a, b

Ricardo Saracino
  • 1,345
  • 2
  • 16
  • 37
1

Regarding how objects are passed to functions you still need to understand that without "&", you pass to the function an object handle , object handle that is still passed by value , and it contains the value of a pointer. But you can not change this pointer until you pass it by reference using the "&"

<?php
        class Example 
        {
            public $value;
         
        }
        
        function test1($x) 
        {
             //let's say $x is 0x34313131
             $x->value = 1;  //will reflect outsite of this function
                             //php use pointer 0x34313131 and search for the 
                             //address of 'value' and change it to 1

        }
        
        function test2($x) 
        {
             //$x is 0x34313131
             $x = new Example;
             //now $x is 0x88888888
             //this will NOT reflect outside of this function 
             //you need to rewrite it as "test2(&$x)"
             $x->value = 1000; //this is 1000 JUST inside this function
                 
        
        }
         
     $example = new Example;
    
     $example->value = 0;
    
     test1($example); // $example->value changed to  1
    
     test2($example); // $example did NOT changed to a new object 
                      // $example->value is still 1
     
 ?>
CGeorgian
  • 551
  • 6
  • 10
0

Actually both methods are valid but it depends upon your requirement. Passing values by reference often makes your script slow. So it's better to pass variables by value considering time of execution. Also the code flow is more consistent when you pass variables by value.

Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
atif
  • 87
  • 1
  • 3
0

Use this for functions when you wish to simply alter the original variable and return it again to the same variable name with its new value assigned.

function add(&$var){ // The &amp; is before the argument $var
   $var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
PPL
  • 6,357
  • 1
  • 11
  • 30
0

A PHP reference is an alias, allowing two different variables to write to the same value.

And in PHP, if you have a variable that contains an object, that variable does not contain the object itself. Instead, it contains an identifier for that object. The object accessor will use the identifier to find the actual object. So when we use the object as an argument in function or assign it to another variable, we will be copying the identifier that points to the object itself.

https://hsalem.com/posts/you-think-you-know-php.html

class Type {}

$x = new Type();
$y = $x;
$y = "New value";

var_dump($x); // Will print the object.
var_dump($y); // Will print the "New value"

$z = &$x; // $z is a reference of $x

$z = "New value";
var_dump($x); // Will print "New value"
var_dump($z); // Will print "New value"

HSLM
  • 1,692
  • 10
  • 25
-8

Depends on the version, 4 is by value, 5 is by reference.

Karl Seguin
  • 21,574
  • 5
  • 44
  • 49
  • 13
    I don't think this is true. – Nick Heiner Aug 17 '09 at 23:44
  • @Karl Seguin, it's partly true. Before PHP5 object by default were passed by value but since 5 they are passed by handler, which in practice can be treated as a reference (with some exceptions) because we can modify object properties via them https://www.php.net/manual/en/language.oop5.references.php. – Navidot Apr 28 '20 at 16:57