normally we would use it like that:
class TestClass
{
public $t;
public function set(\stdClass &$t)
{
$this->t = &$t;
}
}
$obj = new \stdClass();
$obj->fromOUTSIDE = 1;
$test = new TestClass();
$test->set($obj);
var_dump($test);
this results in the desired result:
object(TestClass)#2 (1) {
["t"]=>
&object(stdClass)#1 (1) {
["fromOUTSIDE"]=>
int(1)
}
}
notice the & character, as its a reference. So far so good!
But what if the __get
magic method creates this?
class TestClass
{
public function __get(string $propertyName)
{
$xx = new \stdClass();
$xx->fromGET = 1;
$this->t = &$xx;
return $this->t;
}
}
$test = new TestClass();
$test->t;
var_dump($test);
the reference character disappeared!
object(TestClass)#1 (1) {
["t"]=>
object(stdClass)#2 (1) {
["fromGET"]=>
int(1)
}
}
how to make it referenced? Even using the public function &__get form still no work!
EDIT:
So a basic code:
class X
{
public \stdClass $t;
public function __construct(\stdClass &$t)
{
$this->t = &$t;
}
}
$t = new \stdClass();
$t->TTTT = 1;
$X = new X($t);
var_dump($t);echo "\r\n";
var_dump($X->t);echo "\r\n";
$t = new \stdClass();
$t->TTTT = 2;
var_dump($t);echo "\r\n";
var_dump($X->t);echo "\r\n";
see, it results #1, #1, #3, #1 because renewing the old object wont be affected the object inside the X
.
If I do:
<?php
class X
{
public \stdClass $t;
public function __construct(\stdClass &$t)
{
$this->t = &$t;
}
}
$t = new \stdClass();
$t->TTTT = 1;
$X = new X($t);
var_dump($t);echo "\r\n";
var_dump($X->t);echo "\r\n";
$t = new \stdClass();
$t->TTTT = 2;
var_dump($t);echo "\r\n";
var_dump($X->t);echo "\r\n";
gives the desired result, #1, #1, #3, #3. But what if $t
property doesn't exist? Maybe __get
has to create it or obtain from an object-container. And this is where I can't solve it.
Your t
property will not be a reference because you declare your stdClass
inside the __get
function. Which means that your $xx
will be destroy when the execution of the __get
function is finished.
2 options:
global
variable:<?php
class TestClass
{
public function __get(string $propertyName)
{
global $xx;
$xx = new \stdClass();
$xx->fromGET = 1;
$this->t = &$xx;
return $this->t;
}
}
$test = new TestClass();
$test->t;
var_dump($test);
Result (https://onlinephp.io/c/c9b92):
object(TestClass)#1 (1) {
["t"]=>
&object(stdClass)#2 (1) {
["fromGET"]=>
int(1)
}
}
$xx
outside the __get
function:<?php
class TestClass
{
public function __construct(\stdClass $xx)
{
$this->xx = $xx;
}
public function __get(string $propertyName)
{
$this->xx->fromGET = 1;
$this->t = &$this->xx;
return $this->t;
}
}
$test = new TestClass(new \stdClass());
$test->t;
var_dump($test);
Result (https://onlinephp.io/c/a99f3):
object(TestClass)#1 (2) {
["xx"]=>
&object(stdClass)#2 (1) {
["fromGET"]=>
int(1)
}
["t"]=>
&object(stdClass)#2 (1) {
["fromGET"]=>
int(1)
}
}
Futhermore if you change option 2 and add unset($test->xx)
, you will see that you loose the reference as in your example.
<?php
class TestClass
{
public function __construct(\stdClass $xx)
{
$this->xx = $xx;
}
public function __get(string $propertyName)
{
$this->xx->fromGET = 1;
$this->t = &$this->xx;
return $this->t;
}
}
$test = new TestClass(new \stdClass());
$test->t;
unset($test->xx);
var_dump($test);
Result (https://onlinephp.io/c/801b8):
object(TestClass)#1 (1) {
["t"]=>
object(stdClass)#2 (1) {
["fromGET"]=>
int(1)
}
}