views:

4447

answers:

11

I had a Java developer new to PHP ask me this question the other day, so I thought I'd document the answer here.

Question: are PHP variables passed by value or by reference?

A: 

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

Karl Seguin
I don't think this is true.
Rosarch
+1  A: 

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);

would output "var1: test, var2: final test, var3: final test".

Passed by value/reference exampe:

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

changeThem($var1, $var2);

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

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

would output: "var1: foo, var2 BAR".

Object passed by reference exampe:

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";
}

Would output: "FOO"

(that last example could be better probably...)

cmcculloh
A: 

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

Can you point to some documentation that says that? from everything I've seen, that's not the case...

cmcculloh
+14  A: 

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.'
?>
Michael Stum
+7  A: 

@Karl

In PHP5 variables are by default passed by value and objects are by default passed by reference.

Either can be optionally passed by reference using the & operator.

However, most older PHP functions will not alter a primitive even if you pass a reference...

$str = "hello world";

echo $str; // hello world
echo strrev($str); // dlrow olleh

strrev( &$str ); // ! Warning is issued
echo $str; // hello world

$str = strrev($str);
echo $str; // dlrow olleh

If you do try to pass a value as a reference it will throw a warning. It is up to the function to decide to work on the value or reference.

Kevin
Objects are *not* passed by reference per default. Objects aren't passed at all, object references are passed. By value. No, that's not the same thing.
Michael Borgwardt
@Michael Isn't that implied? Or is there a language where that is not the default behavior?
Kevin
@Kevin: In C++, objects are passed by value per default (if you don't explicitly use pointers). My point is that the statement "objects are by default passed by reference" is wrong about PHP because in PHP, you *don't* pass objects.
Michael Borgwardt
@Michael Ah, thanks for the correction.
Kevin
+7  A: 

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
+2  A: 

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

Flubba
+6  A: 

It seems a lot of people get confused by the way objects are passed to functions and what pass by reference means. Object variables are still passed by value, its 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 swap to:

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

in order to pass by reference.

grom
+1  A: 

You can do it either way.

put a '&' symbol in front and the variable you are passing becomes one and the same as its origin. ie: you can pass by reference, rather than making 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.
Bingy
This is deprecated and generates a warning
fijiaaron
A: 

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
A: 
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