PHP非直接通过引用分配

问题描述 投票:0回答:1

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以及保存该变量状态的可能性。

php reference
1个回答
0
投票

这个问题已经被提及为bug on php.net

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

© www.soinside.com 2019 - 2024. All rights reserved.