PHP 7 将对象推送到数组后覆盖对象会导致覆盖该数组中的所有对象
PHP 7 overwriting an object after pushing it to array results in overwriting of all objects in that array
祝大家愉快。我是 PHP 的新手,在这里我试图将多个对象 ($viewership_prj) 推送到单个数组 ($viewership_prj_arr).
第一次写下面的。结果数组不正确。
基本上,每当将新对象推入数组时,该数组中的所有现有对象都会覆盖新推入对象的属性。
$viewership_prj_arr = array();
$viewership_prj = (object) array();
foreach($projects as $prj)
{
/*...*/
$viewership_prj->title = $prj['project_title'];
$viewership_prj_arr[] = $viewership_prj;
// $viewership_prj_arr[] is [title1] after first loop
// [title2, title2] after second loop
// [title3, title3, title3] after third loop
// ...
}
然后我改成了这个,它起作用了。我在每个循环中声明了一个新对象。
$viewership_prj_arr = array();
foreach($projects as $prj)
{
/*...*/
$viewership_prj = (object) array();
$viewership_prj->title = $prj['project_title'];
$viewership_prj_arr[] = $viewership_prj;
// $viewership_prj_arr[] is [title1] after first loop
// [title1, title2] after second loop
// [title1, title2, title3] after third loop
// ...
}
我很困惑。
我能想到的唯一原因是,当对象被压入数组时,它是通过引用传递的,而不是通过值传递的。我尝试查找手册 https://www.php.net/manual/en/language.oop5.references.php#:~:text=Objects%20and%20references%20%C2%B6,passed%20by%20references%20by%20default%22.&text=A%20PHP%20reference%20is%20an,the%20object%20itself%20as%20value。但对我来说意义不大。
有人可以帮我澄清一下吗?非常感谢。
过于简单化,PHP 将对象存储为
"identifier to object" => actual object
创建新对象$object_1 = (object)[]
存储
"identifier to object 1" => actual object 1
$object_1 = "identifier to object 1"
$object_1
的值是对对象 1 的引用,不是实际对象 本身。它们是两个独立的项目,由标识符链接。
所以,当你这样做时
$object_1->title = "a";
$array[1] = $object_1;
$array[2] = $object_1;
$array[3] = $object_1;
在引擎盖下,它看起来像:
"identifier to object 1" => actual object 1->title = "a"
$array[
1 => "identifier to object 1", // (actual object 1->title = "a")
2 => "identifier to object 1", // (actual object 1->title = "a")
3 => "identifier to object 1", // (actual object 1->title = "a")
];
改变$object_1->title = "b"
套
"identifier to object 1" => actual object 1->title = "b"
但不更改 $array
中的标识符。它们仍然是 “对象 1 的标识符”,因此 所有 数组的元素现在是:
$array[
[1] => "identifier to object 1", // (actual object 1->title = "b")
[2] => "identifier to object 1", // (actual object 1->title = "b")
[3] => "identifier to object 1", // (actual object 1->title = "b")
];
另外 $object_2 = $object_1
只会将 “标识符复制到对象 1”。两个变量都指向同一个对象:
$object_1 = "identifier to object 1"
$object_2 = "identifier to object 1"
任何包含对实际对象 1 的引用的变量 都可以更改 实际对象 1.
$object_1->title = "c";
or
$object_2->title = "c";
or
$array[3]->title = "c";
完全相同,因为它们都包含对同一个实际对象 1 的引用。所以改变一个就是改变所有。
如果您希望所有数组元素都有自己的对象,则必须为每个元素创建一个新对象,或者 - 如果您想使用前一个对象的值 - 使用 clone.
$array = [];
$names = [ "John", "Jack", "Jill" ];
$object = (object)[];
$object->name = "";
$object->coffee = "black with sugar";
foreach( $names as $name ){
$object->name = $val; //change the name of the actual object
$array[] = clone $object; //create a new object with the current values of $object
}
会输出
$array[
stdClass Object ( name=> John, coffee=> black with sugar ),
stdClass Object ( name=> Jack, coffee=> black with sugar ),
stdClass Object ( name=> Jill, coffee=> black with sugar )
]
//$object only contains the last change!
$object = stdClass Object ( name=> Jill, coffee=> black with sugar )
祝大家愉快。我是 PHP 的新手,在这里我试图将多个对象 ($viewership_prj) 推送到单个数组 ($viewership_prj_arr).
第一次写下面的。结果数组不正确。
基本上,每当将新对象推入数组时,该数组中的所有现有对象都会覆盖新推入对象的属性。
$viewership_prj_arr = array();
$viewership_prj = (object) array();
foreach($projects as $prj)
{
/*...*/
$viewership_prj->title = $prj['project_title'];
$viewership_prj_arr[] = $viewership_prj;
// $viewership_prj_arr[] is [title1] after first loop
// [title2, title2] after second loop
// [title3, title3, title3] after third loop
// ...
}
然后我改成了这个,它起作用了。我在每个循环中声明了一个新对象。
$viewership_prj_arr = array();
foreach($projects as $prj)
{
/*...*/
$viewership_prj = (object) array();
$viewership_prj->title = $prj['project_title'];
$viewership_prj_arr[] = $viewership_prj;
// $viewership_prj_arr[] is [title1] after first loop
// [title1, title2] after second loop
// [title1, title2, title3] after third loop
// ...
}
我很困惑。
我能想到的唯一原因是,当对象被压入数组时,它是通过引用传递的,而不是通过值传递的。我尝试查找手册 https://www.php.net/manual/en/language.oop5.references.php#:~:text=Objects%20and%20references%20%C2%B6,passed%20by%20references%20by%20default%22.&text=A%20PHP%20reference%20is%20an,the%20object%20itself%20as%20value。但对我来说意义不大。
有人可以帮我澄清一下吗?非常感谢。
过于简单化,PHP 将对象存储为
"identifier to object" => actual object
创建新对象$object_1 = (object)[]
存储
"identifier to object 1" => actual object 1
$object_1 = "identifier to object 1"
$object_1
的值是对对象 1 的引用,不是实际对象 本身。它们是两个独立的项目,由标识符链接。
所以,当你这样做时
$object_1->title = "a";
$array[1] = $object_1;
$array[2] = $object_1;
$array[3] = $object_1;
在引擎盖下,它看起来像:
"identifier to object 1" => actual object 1->title = "a"
$array[
1 => "identifier to object 1", // (actual object 1->title = "a")
2 => "identifier to object 1", // (actual object 1->title = "a")
3 => "identifier to object 1", // (actual object 1->title = "a")
];
改变$object_1->title = "b"
套
"identifier to object 1" => actual object 1->title = "b"
但不更改 $array
中的标识符。它们仍然是 “对象 1 的标识符”,因此 所有 数组的元素现在是:
$array[
[1] => "identifier to object 1", // (actual object 1->title = "b")
[2] => "identifier to object 1", // (actual object 1->title = "b")
[3] => "identifier to object 1", // (actual object 1->title = "b")
];
另外 $object_2 = $object_1
只会将 “标识符复制到对象 1”。两个变量都指向同一个对象:
$object_1 = "identifier to object 1"
$object_2 = "identifier to object 1"
任何包含对实际对象 1 的引用的变量 都可以更改 实际对象 1.
$object_1->title = "c";
or
$object_2->title = "c";
or
$array[3]->title = "c";
完全相同,因为它们都包含对同一个实际对象 1 的引用。所以改变一个就是改变所有。
如果您希望所有数组元素都有自己的对象,则必须为每个元素创建一个新对象,或者 - 如果您想使用前一个对象的值 - 使用 clone.
$array = [];
$names = [ "John", "Jack", "Jill" ];
$object = (object)[];
$object->name = "";
$object->coffee = "black with sugar";
foreach( $names as $name ){
$object->name = $val; //change the name of the actual object
$array[] = clone $object; //create a new object with the current values of $object
}
会输出
$array[
stdClass Object ( name=> John, coffee=> black with sugar ),
stdClass Object ( name=> Jack, coffee=> black with sugar ),
stdClass Object ( name=> Jill, coffee=> black with sugar )
]
//$object only contains the last change!
$object = stdClass Object ( name=> Jill, coffee=> black with sugar )