【问题标题】:Cloning a PHP object is not working克隆 PHP 对象不起作用
【发布时间】:2016-12-12 22:22:58
【问题描述】:

我遇到了同样的问题about making a copy of an object without reference in PHP,但该解决方案不起作用。

我想获取集合的所有元素,更改一个属性(添加月份)并将新元素推送到新集合中。

所以我使用clone 来获得Invoice 的全新实例,它应该只受到那个实例的影响,但不是。

使用此代码:

while($thisInvoiceYear <= CURRENT_YEAR) {
    $clonedInvoice = clone($thisInvoice);
    $this->extendedInvoices->push($clonedInvoice);
    $toSaveInvoice = $this->extendedInvoices->last();
    $thisInvoiceYear = $this->getCurrentYear($toSaveInvoice);
    $toSaveInvoice->Schedule->StartDate = Carbon::parse($toSaveInvoice->Schedule->StartDate)->addMonths($period);
    unset($clonedInvoice);
}

$thisInvoice 是 Invoice 集合的对象,$this-&gt;extendedInvoices 是 Invoice 类的方法。

问题在于$toSaveInvoice 中所做的每一项更改都会影响到原始集合元素。经过 3 次迭代后,extendedInvoices 的所有元素的日期都相同,不应为:

我正在使用 Laravel 5.2,但我认为没有帮助器来克隆集合的元素。

你知道为什么clone() 不起作用吗?非常感谢您的帮助。

【问题讨论】:

  • 克隆很可能是在做“浅克隆”;您可能需要提供自定义魔术 __clone 方法来执行“深度克隆”(即克隆 Invoice 对象中的所有嵌套对象)

标签: php clone pass-by-reference


【解决方案1】:

一个好主意是先阅读手册,然后再问一个关于 SO 的问题。

来自PHP manual:

创建具有完全复制属性的对象的副本并不总是需要的行为。需要复制构造函数的一个很好的例子是,如果你有一个代表 GTK 窗口的对象,并且该对象拥有这个 GTK 窗口的资源,当你创建一个副本时,你可能想要创建一个具有相同属性的新窗口和让新对象持有新窗口的资源。另一个例子是,如果您的对象拥有对其使用的另一个对象的引用,并且当您复制父对象时,您希望创建该另一个对象的新实例,以便副本拥有自己的单独副本。

使用clone 关键字创建对象副本(如果可能,它会调用对象的__clone() 方法)。不能直接调用对象的__clone()方法。

$copy_of_object = clone $object;

当一个对象被克隆时,PHP 5 将对该对象的所有属性执行一个浅拷贝。任何引用其他变量的属性都将保持引用。

尽管手册描述了 PHP 5 的行为,但根据我自己的经验,我可以向您保证,PHP 7 的行为方式相同。

如果您需要在内部使用其他内容进行克隆,请实现 __clone 方法并定义必须克隆对象的确切内容和方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 2012-03-14
    • 2023-01-27
    • 2018-04-15
    相关资源
    最近更新 更多