PHP对象数组要求我克隆每个对象,否则它将持续更改

时间:2018-06-07 03:53:29

标签: php arrays object foreach

我有一个包含对象数组的类。 我有一个循环遍历数组的函数,并格式化一个值,然后只是将这些格式化的值放入一个单独的数组中......然后返回它们。

以下是相关代码:

class MoneyThing {
    public $taxes = array();

    public function formatTaxes(){
        // Pretend the $taxes array is populated as such when called, with a single LeviedTax object
        //  Array
        //  (
        //      [0] => LeviedTax Object
        //      (
        //          [name] => HST
        //          [rate] => 13
        //          [total] => 17.55
        //          [harmonized] => 1
        //      )
        //  )

        echo "<pre>".print_r($this->taxes, true)."</pre>";

        $formattedTaxes = $this->taxes;

        foreach($formattedTaxes as $tax){
            // Make a clone of the object.  PHP object are copied to other vars by reference by default.
            // $tax = clone $tax;

            // Just adds a dollar sign
            $tax->total = money_format($tax->total);
            $formattedTaxes[] = $tax;
        }

        echo "<pre>".print_r($this->taxes, true)."</pre>";

        // Will print the 'total' with a dollar sign. Why???:
        //  Array
        //  (
        //      [0] => LeviedTax Object
        //      (
        //          [name] => HST
        //          [rate] => 13
        //          [total] => $17.55
        //          [harmonized] => 1
        //      )
        //  )

        return $formattedTaxes;
    }
}

我在foreach循环之前和之后打印了类的数组。我看到数组保留了这些更改,就像我在foreach中直接引用它们一样。我期望在循环之前和之后拥有相同的数组,因为我甚至没有使用所述数组。

据我所知,Arrays复制简单明了,而Objects则通过引用复制。但是,由于我正在复制一组对象,我希望不必使用克隆,因为它不是通过引用...对吗?

为了不实际保留格式化的值,为什么我必须取消注释$tax = clone $tax;

1 个答案:

答案 0 :(得分:3)

对象始终通过引用传递。 从技术上讲,PHP中的对象数组是对象的引用数组。

从设计角度来看,你正试图解决错误的问题。

说实话,你不需要这种方法。像money_format()这样的调用应该在税收输出时实施,例如,当您将其插入HTML或写入CSV时。

如果你真的需要多次输出这个东西,例如你必须将格式化的税值打印成几十​​种不同的文件格式,那么值得在formattedTotal属性的形式上引入一点开销。 LeviedTax课程。在这种情况下,您将拥有一个像

这样的setter
class LeviedTax {
  public function setTotal($total) {
    $this->total = $total;
    $this->formattedTotal = money_format($total);
  }
}