在迭代对象数组时,我对for循环的行为有点困惑。
foreach (array_expression as $key => $value)
为了能够直接修改循环中的数组元素,在$ value之前加上&amp ;.在这种情况下,该值将通过引用分配。
基于此,我的印象是$value
是数组中对象的副本(按值)。但是,要验证我刚刚运行此测试:
class test {
public $foo = 1;
function __construct($foo) {
$this->foo = $foo;
}
}
$testArray = array();
$testArray[] = new test(1);
$testArray[] = new test(2);
$testArray[] = new test(3);;
echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';
foreach ($testArray as $test) {
if ($test->foo == 2) {
$temp = $test;
}
}
$temp->foo = 'copied by value or reference?';
echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';
令人惊讶的是,输出是:
$testArray
Array
(
[0] => test Object
(
[foo] => 1
)
[1] => test Object
(
[foo] => 2
)
[2] => test Object
(
[foo] => 3
)
)
$testArray
Array
(
[0] => test Object
(
[foo] => 1
)
[1] => test Object
(
[foo] => copied by value or reference?
)
[2] => test Object
(
[foo] => 3
)
)
我的困惑是,当我执行$temp = $test
赋值时,它通过引用数组中的原始对象来复制,但我认为$test
已根据文档按值复制了?< / p>
好的,也许我只是没有注意细则:
为了能够直接修改>中的数组元素在$ value之前用&amp ;.在这种情况下,该值将通过引用分配。
所以让我们尝试一下我们修改循环内对象的测试:
class test {
public $foo = 1;
function __construct($foo) {
$this->foo = $foo;
}
}
$testArray = array();
$testArray[] = new test(1);
$testArray[] = new test(2);
$testArray[] = new test(3);;
echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';
foreach ($testArray as $test) {
if ($test->foo == 2) {
$temp = $test;
$temp->foo = 'copied by value or reference?';
}
}
echo '$testArray' . '<pre>' . PHP_EOL;
print_r($testArray);
echo PHP_EOL . '</pre>';
输出:
$testArray
Array
(
[0] => test Object
(
[foo] => 1
)
[1] => test Object
(
[foo] => 2
)
[2] => test Object
(
[foo] => 3
)
)
$testArray
Array
(
[0] => test Object
(
[foo] => 1
)
[1] => test Object
(
[foo] => copied by value or reference?
)
[2] => test Object
(
[foo] => 3
)
)
结果是一样的。看来该对象是通过引用复制的,即使文档明确暗示它们是按值复制的。
是什么给出了?
答案 0 :(得分:3)
从PHP 5开始,对象变量不包含对象本身 价值了。它只包含允许的对象标识符 对象访问器来查找实际对象。当一个对象被发送时 参数,返回或分配给另一个变量,不同 变量不是别名:它们包含标识符的副本,即 指向同一个对象。
http://php.net/manual/en/language.oop5.references.php
编辑:我第一次遇到相反的问题,我需要按值复制对象。
就像$new_obj = clone $original_obj
一样,如果你的对象很简单......如果你有一个包含其他对象的对象,最终会在数组或子数组中变成一场噩梦!在不同类中有几个__clone()
魔术函数,对于一些棘手的案例有些令人头疼......
我终于消灭了所有这些clone
和__clone()
的东西并选择了以下解决方案:
$new_obj = unserialize(serialize($original_obj));
这里有关这个解决方案的有趣的赞成/评论,在我的案例中是最好的 - 或者至少是最简单的:-): How do I create a copy of an object in PHP?