In this code:
<?php
class Foo
{
var $value;
function foo($value)
{
$this->setValue($value);
}
function setValue($value)
{
$this->value=$value;
}
}
class Bar
{
var $foos=array();
function Bar()
{
for ($x=1; $x<=10; $x++)
{
$this->foos[$x]=new Foo("Foo # $x");
}
}
function getFoo($index)
{
return $this->foos[$index];
}
function test()
{
$testFoo=$this->getFoo(5);
$testFoo->setValue("My value has now changed");
}
}
?>
When the method Bar::test() is run and it changes the value of foo # 5 in the array of foo objects, will the actual foo # 5 in the array be affected, or will the $testFoo variable be only a local variable which would cease to exist at the end of the function?
Why not run the function and find out?
$b = new Bar;
echo $b->getFoo(5)->value;
$b->test();
echo $b->getFoo(5)->value;
For me the above code (along with your code) produced this output:
Foo #5
My value has now changed
This isn't due to "passing by reference", however, it is due to "assignment by reference". In PHP 5 assignment by reference is the default behaviour with objects. If you want to assign by value instead, use the clone keyword.
You can refer to http://ca2.php.net/manual/en/language.oop5.references.php for the actual answer to your question.
One of the key-points of PHP5 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 PHP5, 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.
They are passed by value in PHP 4 and by reference in PHP 5. In order to pass objects by reference in PHP 4 you have to explicitly mark them as such:
$obj = &new MyObj;
Related
In this code:
<?php
class Foo
{
var $value;
function foo($value)
{
$this->setValue($value);
}
function setValue($value)
{
$this->value=$value;
}
}
class Bar
{
var $foos=array();
function Bar()
{
for ($x=1; $x<=10; $x++)
{
$this->foos[$x]=new Foo("Foo # $x");
}
}
function getFoo($index)
{
return $this->foos[$index];
}
function test()
{
$testFoo=$this->getFoo(5);
$testFoo->setValue("My value has now changed");
}
}
?>
When the method Bar::test() is run and it changes the value of foo # 5 in the array of foo objects, will the actual foo # 5 in the array be affected, or will the $testFoo variable be only a local variable which would cease to exist at the end of the function?
Why not run the function and find out?
$b = new Bar;
echo $b->getFoo(5)->value;
$b->test();
echo $b->getFoo(5)->value;
For me the above code (along with your code) produced this output:
Foo #5
My value has now changed
This isn't due to "passing by reference", however, it is due to "assignment by reference". In PHP 5 assignment by reference is the default behaviour with objects. If you want to assign by value instead, use the clone keyword.
You can refer to http://ca2.php.net/manual/en/language.oop5.references.php for the actual answer to your question.
One of the key-points of PHP5 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 PHP5, 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.
They are passed by value in PHP 4 and by reference in PHP 5. In order to pass objects by reference in PHP 4 you have to explicitly mark them as such:
$obj = &new MyObj;
$a = some object;
$b = another object;
function do_some_stuff() {
$c = $a;
$b->a_property = $c;
}
do_some_stuff();
echo $b->a_property; # Undefined, becuase $c was deleted when the function exited.
When I type $b->a_property = $c, I want the PHP interpereter to do $b->a_property = $a. How do I do that, if I'm unable to assign it to $a directly?
My actual code is:
function setup() {
$playerHeroes = [];
$enemyHeroes = [];
foreach ($entities as $object) {
if ($object->team == "player") {
$playerHeroes[] = $object;
}
else if ($object->team == "enemy") {
$enemyHeroes[] = $object;
}
}
foreach ($playerHeroes as $object) {
$object->target = $enemyHeroes[array_rand($enemyHeroes)];
}
foreach ($enemyHeroes as $object) {
$object->target = $playerHeroes[array_rand($playerHeroes)];
}
}
I sort through a list of entities in the game as either being on the player's team or being on the enemy's team. Each hero must target a hero on the opposing team. When the setup function exits, $object, $playerHeroes and $enemyHeroes get destroyed. The ->target properties are accessed later, and it's null. How do I make it so that when I assign a variable to a reference of an object, it assigns it to the object itself?
EDIT: I want the variable to change when the object changes, so cloning/copying by value is not an option.
In addition to echoing the comments from #IvoP and #mega6382, it's worth noting that the problem you're having is not a "solvable" one per se. That's because what you're running into is fundamental to how objects work in PHP. You can learn all about it at http://ca2.php.net/manual/en/language.oop5.references.php.
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. This section rectifies that general thought using some examples.
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.
(hat tip to #tomzx)
You'll likely do better to rearchitect your code to deal with this or use a language whose default behavior is call-by-value like C or Java.
Since objects are passed by reference by default now, is there maybe some special case when &$obj would make sense?
Objects use a different reference mechanism. &$object is more a reference of a reference. You can't really compare them both.
See Objects and references:
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.
&$object is something else than $object. I'll give you an example:
foreach ($objects as $object) {
if ($cond) {
$object = new Object(); // This won't affect $objects
}
}
foreach ($objects as &$object) {
if ($cond) {
$object = new Object(); // This will affect $objects
}
}
I won't answer the question if it makes sense, or if there is a need. These are opinion based questions. You can definitely live without the & reference on objects, as you could without objects at all. The existence of two mechanisms is a consequence of PHP's backward compatibility.
There are situations where you add & in front of function name, to return any value as a reference.
To call those function we need to add & in front of object.
If we add & in front of object, then it will return value as reference otherwise it will only return a copy of that variable.
class Fruit() {
protected $intOrderNum = 10;
public function &getOrderNum() {
return $this->intOrderNum;
}
}
class Fruitbox() {
public function TestFruit() {
$objFruit = new Fruit();
echo "Check fruit order num : " . $objFruit->getOrderNum(); // 10
$intOrderNumber = $objFruit->getOrderNum();
$intOrderNumber++;
echo "Check fruit order num : " . $objFruit->getOrderNum(); // 10
$intOrderNumber = &$objFruit->getOrderNum();
$intOrderNumber++;
echo "Check fruit order num : " . $objFruit->getOrderNum(); // 11
}
}
In PHP 5, are you required to use the & modifier to pass by reference? For example,
class People() { }
$p = new People();
function one($a) { $a = null; }
function two(&$a) { $a = null; )
In PHP4 you needed the & modifier to maintain reference after a change had been made, but I'm confused on the topics I have read regarding PHP5's automatic use of pass-by-reference, except when explicity cloning the object.
In PHP5, is the & modifier required to pass by reference for all types of objects (variables, classes, arrays, ...)?
are you required to use the & modifier to pass-by-reference?
Technically/semantically, the answer is yes, even with objects. This is because there are two ways to pass/assign an object: by reference or by identifier. When a function declaration contains an &, as in:
function func(&$obj) {}
The argument will be passed by reference, no matter what. If you declare without the &
function func($obj) {}
Everything will be passed by value, with the exception of objects and resources, which will then be passed via identifier. What's an identifier? Well, you can think of it as a reference to a reference. Take the following example:
class A
{
public $v = 1;
}
function change($obj)
{
$obj->v = 2;
}
function makezero($obj)
{
$obj = 0;
}
$a = new A();
change($a);
var_dump($a);
/*
output:
object(A)#1 (1) {
["v"]=>
int(2)
}
*/
makezero($a);
var_dump($a);
/*
output (same as before):
object(A)#1 (1) {
["v"]=>
int(2)
}
*/
So why doesn't $a suddenly become an integer after passing it to makezero? It's because we only overwrote the identifier. If we had passed by reference:
function makezero(&$obj)
{
$obj = 0;
}
makezero($a);
var_dump($a);
/*
output:
int(0)
*/
Now $a is an integer. So, there is a difference between passing via identifier and passing via reference.
Objects will pass-by-reference. Built in types will be pass-by-value (copied);
What is happening behind the scenes is that when you pass in a variable that holds an object, it's a reference to the object. So the variable itself is copied, but it still references the same object. So, essentially there are two variable, but both are pointing to the same object. Changes made to objects inside a function will persist.
In the case of the code that you have there (first you need $ even with &):
$original = new Object();
one($original); //$original unaffected
two($original); //$original will now be null
function one($a) { $a = null; } //This one has no impact on your original variable, it will still point to the object
function two(&$a) { $a = null; ) //This one will set your original variable to null, you'll lose the reference to the object.
You're using it wrong. The $ sign is compulsory for any variable. It should be:
http://php.net/manual/en/language.references.pass.php
function foo(&$a)
{
$a=null;
}
foo($a);
To return a reference, use
function &bar($a){
$a=5;
return $a
}
In objects and arrays, a reference to the object is copied as the formal parameter, any equality operations on two objects is a reference exchange.
$a=new People();
$b=$a;//equivalent to &$b=&$a roughly. That is the address of $b is the same as that of $a
function goo($obj){
//$obj=$e(below) which essentially passes a reference of $e to $obj. For a basic datatype such as string, integer, bool, this would copy the value, but since equality between objects is anyways by references, this results in $obj as a reference to $e
}
$e=new People();
goo($e);
In this code:
<?php
class Foo
{
var $value;
function foo($value)
{
$this->setValue($value);
}
function setValue($value)
{
$this->value=$value;
}
}
class Bar
{
var $foos=array();
function Bar()
{
for ($x=1; $x<=10; $x++)
{
$this->foos[$x]=new Foo("Foo # $x");
}
}
function getFoo($index)
{
return $this->foos[$index];
}
function test()
{
$testFoo=$this->getFoo(5);
$testFoo->setValue("My value has now changed");
}
}
?>
When the method Bar::test() is run and it changes the value of foo # 5 in the array of foo objects, will the actual foo # 5 in the array be affected, or will the $testFoo variable be only a local variable which would cease to exist at the end of the function?
Why not run the function and find out?
$b = new Bar;
echo $b->getFoo(5)->value;
$b->test();
echo $b->getFoo(5)->value;
For me the above code (along with your code) produced this output:
Foo #5
My value has now changed
This isn't due to "passing by reference", however, it is due to "assignment by reference". In PHP 5 assignment by reference is the default behaviour with objects. If you want to assign by value instead, use the clone keyword.
You can refer to http://ca2.php.net/manual/en/language.oop5.references.php for the actual answer to your question.
One of the key-points of PHP5 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 PHP5, 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.
They are passed by value in PHP 4 and by reference in PHP 5. In order to pass objects by reference in PHP 4 you have to explicitly mark them as such:
$obj = &new MyObj;