Reputation:
I have a bit of a general dissatisfaction about the way passing by reference works in PHP, coming from a Java background myself. This might have been talked about before on SO, so I'm sorry if this might seem redundant.
I'm going to give a code example to make things clear. Say we have a Person class:
<?php
class Person
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
?>
and the following usage:
<?php
require_once __DIR__ . '/Person.php';
function changeName(Person $person)
{
$person->setName("Michael");
}
function changePerson(Person $person)
{
$person = new Person("Jerry");
}
$person = new Person("John");
changeName($person);
echo $person->getName() . PHP_EOL;
changePerson($person);
echo $person->getName() . PHP_EOL;
?>
Now I, and many others coming from programming in Java or C# into PHP, would expect the above code to output:
Michael
Jerry
However, it does not, it outputs:
Michael
Michael
I know it can be fixed by using &. From looking into it, I understand that this is because the reference is passed into the function by value (a copy of the reference). But this to me constitutes an unexpected / inconsistent behavior, so the question would be: Is there any particular reason or benefit for which they chose to do it this way?
Upvotes: 4
Views: 194
Reputation: 16055
Your code would work as expected if used this way:
function changePerson(Person &$person) // <- & to state the reference
{
$person = new Person("Jerry");
}
$person = new Person("John");
changeName($person);
echo $person->getName() . PHP_EOL;
changePerson($person);
echo $person->getName() . PHP_EOL;
See the output: http://codepad.org/eSt4Xcpr
One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default". This is not completely true.
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
Quoted from http://php.net/manual/en/language.oop5.references.php.
Upvotes: 1
Reputation: 91734
The object itself is actually passed by reference, otherwise your first echo
would not output Michael
.
What happens in your second example is that you destroy the (local) reference to the original object and have your variable name reference a new object that has a local scope in the function.
That makes sense to me as you could destroy / replace your object with something completely different by simply assigning a new value to the variable in the function.
Upvotes: 2