【问题标题】:Laravel original variable affects temporary variableLaravel 原始变量影响临时变量
【发布时间】:2021-01-08 15:13:35
【问题描述】:

我试图将原始数据保存在一个名为 $copyItems 的临时变量中,但每当我更改原始变量 $items 的值时,复制的变量也会发生变化。

举个例子:

$items = \App\Models\Customers::with('Account')->get();
$copyItems = $items; // Should hold all the original $items values no matter the changes

// Prints "Stackoverflow"
echo $copyItems[0]->Account->name;

$items[0]->Account->name = 'John';

// Prints "John" and should print "Stackoverflow"
echo $copyItems[0]->Account->name;

这到底是怎么回事?我没有使用变量引用&$items 为什么我的临时变量被更改了?

使用clone $items 方法,结果是一样的。

【问题讨论】:

  • stackoverflow.com/questions/23895126/… 这可能对你有帮助
  • @SandroVardiashvili ->replicate() 在数据库中创建一个新行,我不想要它。
  • 当您将一个对象分配给另一个变量时,您并没有“复制”它......两个变量都指向同一个对象......并且调用clone只会克隆集合,而不是克隆每个对象,所以即使是新的 Collection 也将包含与另一个完全相同的对象
  • 在这种情况下,您可以将 Laravel 集合用于 $copyItems,然后执行 $copyItems = collect($items);
  • @SandroVardiashvili collect($items) 在我的情况下工作得很好,这样我就不需要做另一个数据库查询。将其设置为答案,我会接受。

标签: php laravel


【解决方案1】:

当您将对象分配给另一个变量时,您并没有复制它。 $copyItems$items 指向同一个对象。

克隆在这里没有帮助,因为clone 将复制 Collection 实例。这两个集合的项目实际上都指向相同的对象,因为 clone 不会克隆集合中的每个对象,它只是克隆 Collection 对象本身。

基本上,变量不保存对象,它包含一个标识符。这就是为什么你听到/看到人们说对象总是通过引用传递的,这足以理解但并不完全正确。 PHP 手册对此做了一些解释。

“从 PHP 5 开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问器找到实际对象。当对象通过参数发送时,返回或 分配给另一个变量,不同的变量不是别名:它们持有标识符的副本,它指向同一个对象。”

PHP.net Manual - OOP - Objects and References

【讨论】:

    【解决方案2】:

    您可以将 Laravel 集合用于$copyItems

    $copyItems = collect($items);

    【讨论】:

      【解决方案3】:

      不,它应该打印 stackoverflow。如果换个角度看。

      $items = \App\Models\Customers::with('Account')->get();
      $copyItems = $items;
      

      以上意思是:

      $items = \App\Models\Customers::with('Account')->get();
      $copyItems = \App\Models\Customers::with('Account')->get();
      

      然后运行:

      echo $copyItems[0]->Account->name;
      

      所以它打印出stackoverflow。然后运行:

      $items[0]->Account->name = 'John';
      

      上面的命令基本意思是:

      $copyItems[0]->Account->name = 'John';
      

      这就是你的下一个命令输出 John 的原因:

      echo $copyItems[0]->Account->name;
      

      【讨论】:

      • 不,它不应该为第二个回显打印'stackoverflow',他们看到的输出是正确的......分配时不会复制对象......这两个变量都指向相同的确切值他们的例子中的对象
      猜你喜欢
      • 2013-11-25
      • 2016-09-05
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 2013-03-06
      • 2011-05-19
      • 2018-01-28
      • 1970-01-01
      相关资源
      最近更新 更多