class ClassA { private $fields; public function test1() { $this->fields = array(1,2,3); foreach ($this->fields as &$v) { $v += 1; } $localFields = array('x','y','z'); foreach ($localFields as $v) { } echo json_encode($this->fields); // expect: [2,3,4], output: [2,3,"z"] } public function test2() { $this->fields = array(1,2,3); foreach ($this->fields as &$v) { $v += 1; } $v = 'abc'; echo json_encode($this->fields); // expect: [2,3,4], output: [2,3,"abc"] } public function test3() { $this->fields = array(1,2,3); foreach ($this->fields as &$v) { $v += 1; } $this->inner(); } private function inner() { $v = '***'; echo json_encode($this->fields); // output: [2,3,4] } } $obj = new ClassA(); $obj->test1(); $obj->test2(); $obj->test3();
上面可以看到,雖然第一次使用 &$v
是在迴圈中,第二次使用 $v
是在另一個迴圈。
原本預想應該是互不相關,但是顯然 Call By Reference 影響到第一次使用的欄位,造成出乎意料的狀況。
解決的方法:使用完 &$v
之後就馬上 unset($v);
缺點是可能會看不懂為什麼這樣做。
比較好的作法還是改用索引存取:
foreach ($this->fields as $k => $v) { $this->fields[$k] = $v + 1; }
PHP 5.3.24 (cli) (built: Jun 10 2013 16:42:20) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies with Xdebug v2.2.0rc1, Copyright (c) 2002-2012, by Derick Rethans