简体   繁体   English

php,我无法将属性设置为来自 __get 的引用,有什么解决方法吗?

[英]php, I cant set property as reference from __get, any workaround?

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 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?但是,如果__get魔法方法创建了这个呢?

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 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!即使使用公共 function &__get 表单仍然无效!

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

https://onlinephp.io/c/9cd7a 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 .看,结果是#1、#1、#3、#1,因为更新旧的 object 不会影响X内的 object。 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";

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

gives the desired result, #1, #1, #3, #3.给出期望的结果,#1,#1,#3,#3。 But what if $t property doesn't exist?但是,如果$t属性不存在怎么办? Maybe __get has to create it or obtain from an object-container.也许__get必须创建它或从对象容器中获取。 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.您的t属性将不是引用,因为您在__get function 中声明了您的stdClass 。这意味着您的$xx将在__get function 执行完成时被销毁。

How can you do it so?你怎么能这样做?

2 options: 2个选项:

  1. Create a global variable:创建一个global变量:
<?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 ):结果( https://onlinephp.io/c/c9b92 ):

object(TestClass)#1 (1) {
  ["t"]=>
  &object(stdClass)#2 (1) {
    ["fromGET"]=>
    int(1)
  }
}
  1. Declare $xx outside the __get function:__get function 之外声明$xx
<?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 ):结果( 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.此外,如果您更改选项 2 并添加unset($test->xx) ,您将看到您丢失了示例中的引用。

<?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 ):结果( https://onlinephp.io/c/801b8 ):

object(TestClass)#1 (1) {
  ["t"]=>
  object(stdClass)#2 (1) {
    ["fromGET"]=>
    int(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.我对此不是 100%,但如果我正确理解你的问题,我相信你的代码实际上做了你期望它做的事情。 However creating a reference is not nessecary.但是,创建引用并不是必需的。

There is only one reference to the stdClass object in this case.在这种情况下,只有一个对stdClass object 的引用。 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM