skip to Main Content

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

https://onlinephp.io/c/cf4e3

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

https://onlinephp.io/c/21f4f

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 "rn";
var_dump($X->t);echo "rn";

$t = new stdClass();
$t->TTTT = 2;

var_dump($t);echo "rn";
var_dump($X->t);echo "rn";

https://onlinephp.io/c/9cd7a

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 "rn";
var_dump($X->t);echo "rn";

$t = new stdClass();
$t->TTTT = 2;

var_dump($t);echo "rn";
var_dump($X->t);echo "rn";

https://onlinephp.io/c/8efd4

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.

2

Answers


  1. I’m not 100% on this, but if I understand your question correctly I believe your code actually does what you expect it to do. However creating a reference is not nessecary.

    There is only one reference to the stdClass object in this case. Therefor the representation with the ampersand is not nessesary.

    If you add another reference is should appear:

    <?php
    class TestClass
    {
        public function __get(string $propertyName)
        {
            $xx = new StdClass();
            $xx->fromGET = 1;
            $this->t = $xx; // no reference needed here
            return $this->t;
        }
    }
    
    $test = new TestClass();
    $test->t;
    
    // another Reference to the object is created
    $t =& $test->t;
    var_dump($test);
    
    Login or Signup to reply.
  2. 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.

    How can you do it so ?

    2 options:

    1. Create a 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)
      }
    }
    
    1. Declare $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)
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search