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
沒有留言:
張貼留言