PHP非直接指定引用

时间:2017-12-29 04:35:37

标签: php reference

PHP 7.0

我注意到分配数组时的奇怪行为。 PHP中的数组应该通过值复制来分配(如果不直接设置为引用)。

在本地范围内引用一次的变量在任何地方都被引用(这就是我猜的)。在我看来,这不是它应该如何运作。我想在一个地方创建引用,但在其他地方复制值。

请看一下这个例子

class A
{

    public $b;

    public $refVar;

    public function __construct(B $b)
    {
        $this->b = $b;

        // reference here
        $this->refVar = &$this->b->vars['randoms'];
    }

}

class B
{

    public $vars = [];
    public $history = [];


    public function __construct()
    {
        $this->vars['randoms'] = [];
    }

    public function doSomething()
    {
        // copy value here
        $this->history[] = $this->vars;

        $this->vars['randoms'][] = rand();
    }

}

$b = new B();

echo "After B::__construct\n";
var_dump($b->vars);

$a = new A($b);

echo "\n\nAfter A::__construct(B)\n";
var_dump($b->vars);

$b->doSomething();

echo "\n\nAfter B::doSomething()\n";
var_dump($b->vars);

$b->doSomething();
$b->doSomething();

echo "\n\nB::history\n";
var_dump($b->history);

结果

After B::__construct
array(1) {
  ["randoms"]=>
  array(0) {
  }
}


After A::__construct(B)
array(1) {
  ["randoms"]=>
  &array(0) {
  }
}


After B::doSomething()
array(1) {
  ["randoms"]=>
  &array(1) {
    [0]=>
    int(85799664)
  }
}


B::history
array(3) {
  [0]=>
  array(1) {
    ["randoms"]=>
    &array(3) {
      [0]=>
      int(85799664)
      [1]=>
      int(418164754)
      [2]=>
      int(1267239969)
    }
  }
  [1]=>
  array(1) {
    ["randoms"]=>
    &array(3) {
      [0]=>
      int(85799664)
      [1]=>
      int(418164754)
      [2]=>
      int(1267239969)
    }
  }
  [2]=>
  array(1) {
    ["randoms"]=>
    &array(3) {
      [0]=>
      int(85799664)
      [1]=>
      int(418164754)
      [2]=>
      int(1267239969)
    }
  }
}

code fiddle

正如您所看到的那样,在A :: __构造范围内引用B :: vars会使B :: vars无处不在。

如何防止这种情况?

编辑:经过长时间的研究,我简化了一些例子。并发现了什么是错的 - 但我不知道如何防止这种情况。

Meta:没有人回答,所以我改变了一个小问题。我不想关闭它,因为有人已经跟着它。

编辑2 我发布的解决方案并不完全令人满意。 如果有人知道如何克服这个问题(可能通过改变概念),欢迎任何建议。但请记住,需要在A类中引用B :: vars以及保存该变量状态的可能性。

1 个答案:

答案 0 :(得分:0)

此问题已作为bug on php.net

提及

似乎唯一的解决方案是使用serialize或json_encode - 这会对性能产生很大影响。